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_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n, st; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 207 PetscCall(MatGetSize(mat, &N, NULL)); 208 PetscCall(MatGetLocalSize(mat, &n, NULL)); 209 PetscCall(VecSet(l, 0.0)); 210 PetscCall(VecSetRandom(r, NULL)); 211 PetscCall(MatMult(mat, r, l)); 212 PetscCall(VecGetArrayRead(l, &al)); 213 } else { /* nonzero columns */ 214 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 215 PetscCall(MatGetSize(mat, NULL, &N)); 216 PetscCall(MatGetLocalSize(mat, NULL, &n)); 217 PetscCall(VecSet(r, 0.0)); 218 PetscCall(VecSetRandom(l, NULL)); 219 PetscCall(MatMultTranspose(mat, l, r)); 220 PetscCall(VecGetArrayRead(r, &al)); 221 } 222 if (tol <= 0.0) { 223 for (i = 0, nz = 0; i < n; i++) 224 if (al[i] != 0.0) nz++; 225 } else { 226 for (i = 0, nz = 0; i < n; i++) 227 if (PetscAbsScalar(al[i]) > tol) nz++; 228 } 229 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 230 if (gnz != N) { 231 PetscInt *nzr; 232 PetscCall(PetscMalloc1(nz, &nzr)); 233 if (nz) { 234 if (tol < 0) { 235 for (i = 0, nz = 0; i < n; i++) 236 if (al[i] != 0.0) nzr[nz++] = i + st; 237 } else { 238 for (i = 0, nz = 0; i < n; i++) 239 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 240 } 241 } 242 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 243 } else *nonzero = NULL; 244 if (!cols) { /* nonzero rows */ 245 PetscCall(VecRestoreArrayRead(l, &al)); 246 } else { 247 PetscCall(VecRestoreArrayRead(r, &al)); 248 } 249 PetscCall(VecDestroy(&l)); 250 PetscCall(VecDestroy(&r)); 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 /*@ 255 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 256 257 Input Parameter: 258 . mat - the matrix 259 260 Output Parameter: 261 . keptrows - the rows that are not completely zero 262 263 Level: intermediate 264 265 Note: 266 `keptrows` is set to `NULL` if all rows are nonzero. 267 268 Developer Note: 269 If `keptrows` is not `NULL`, it must be sorted. 270 271 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 272 @*/ 273 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 274 { 275 PetscFunctionBegin; 276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 277 PetscValidType(mat, 1); 278 PetscAssertPointer(keptrows, 2); 279 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 280 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 281 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 282 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 283 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindZeroRows - Locate all rows that are completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . zerorows - the rows that are completely zero 295 296 Level: intermediate 297 298 Note: 299 `zerorows` is set to `NULL` if no rows are zero. 300 301 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 302 @*/ 303 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 304 { 305 IS keptrows; 306 PetscInt m, n; 307 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(zerorows, 2); 312 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 313 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 314 In keeping with this convention, we set zerorows to NULL if there are no zero 315 rows. */ 316 if (keptrows == NULL) { 317 *zerorows = NULL; 318 } else { 319 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 320 PetscCall(ISComplement(keptrows, m, n, zerorows)); 321 PetscCall(ISDestroy(&keptrows)); 322 } 323 PetscFunctionReturn(PETSC_SUCCESS); 324 } 325 326 /*@ 327 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 328 329 Not Collective 330 331 Input Parameter: 332 . A - the matrix 333 334 Output Parameter: 335 . a - the diagonal part (which is a SEQUENTIAL matrix) 336 337 Level: advanced 338 339 Notes: 340 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 341 342 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 343 344 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 345 @*/ 346 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 347 { 348 PetscFunctionBegin; 349 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 350 PetscValidType(A, 1); 351 PetscAssertPointer(a, 2); 352 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 353 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 354 else { 355 PetscMPIInt size; 356 357 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 358 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 359 *a = A; 360 } 361 PetscFunctionReturn(PETSC_SUCCESS); 362 } 363 364 /*@ 365 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 366 367 Collective 368 369 Input Parameter: 370 . mat - the matrix 371 372 Output Parameter: 373 . trace - the sum of the diagonal entries 374 375 Level: advanced 376 377 .seealso: [](ch_matrices), `Mat` 378 @*/ 379 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 380 { 381 Vec diag; 382 383 PetscFunctionBegin; 384 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 385 PetscAssertPointer(trace, 2); 386 PetscCall(MatCreateVecs(mat, &diag, NULL)); 387 PetscCall(MatGetDiagonal(mat, diag)); 388 PetscCall(VecSum(diag, trace)); 389 PetscCall(VecDestroy(&diag)); 390 PetscFunctionReturn(PETSC_SUCCESS); 391 } 392 393 /*@ 394 MatRealPart - Zeros out the imaginary part of the matrix 395 396 Logically Collective 397 398 Input Parameter: 399 . mat - the matrix 400 401 Level: advanced 402 403 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 404 @*/ 405 PetscErrorCode MatRealPart(Mat mat) 406 { 407 PetscFunctionBegin; 408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 409 PetscValidType(mat, 1); 410 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 411 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 412 MatCheckPreallocated(mat, 1); 413 PetscUseTypeMethod(mat, realpart); 414 PetscFunctionReturn(PETSC_SUCCESS); 415 } 416 417 /*@C 418 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 419 420 Collective 421 422 Input Parameter: 423 . mat - the matrix 424 425 Output Parameters: 426 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 427 - ghosts - the global indices of the ghost points 428 429 Level: advanced 430 431 Note: 432 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 433 434 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 435 @*/ 436 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 437 { 438 PetscFunctionBegin; 439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 440 PetscValidType(mat, 1); 441 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 442 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 443 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 444 else { 445 if (nghosts) *nghosts = 0; 446 if (ghosts) *ghosts = NULL; 447 } 448 PetscFunctionReturn(PETSC_SUCCESS); 449 } 450 451 /*@ 452 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 453 454 Logically Collective 455 456 Input Parameter: 457 . mat - the matrix 458 459 Level: advanced 460 461 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 462 @*/ 463 PetscErrorCode MatImaginaryPart(Mat mat) 464 { 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 467 PetscValidType(mat, 1); 468 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 469 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 470 MatCheckPreallocated(mat, 1); 471 PetscUseTypeMethod(mat, imaginarypart); 472 PetscFunctionReturn(PETSC_SUCCESS); 473 } 474 475 /*@ 476 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 477 478 Not Collective 479 480 Input Parameter: 481 . mat - the matrix 482 483 Output Parameters: 484 + missing - is any diagonal entry missing 485 - dd - first diagonal entry that is missing (optional) on this process 486 487 Level: advanced 488 489 Note: 490 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 491 492 .seealso: [](ch_matrices), `Mat` 493 @*/ 494 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 495 { 496 PetscFunctionBegin; 497 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 498 PetscValidType(mat, 1); 499 PetscAssertPointer(missing, 2); 500 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 501 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 502 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 503 PetscFunctionReturn(PETSC_SUCCESS); 504 } 505 506 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 507 /*@C 508 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 509 for each row that you get to ensure that your application does 510 not bleed memory. 511 512 Not Collective 513 514 Input Parameters: 515 + mat - the matrix 516 - row - the row to get 517 518 Output Parameters: 519 + ncols - if not `NULL`, the number of nonzeros in `row` 520 . cols - if not `NULL`, the column numbers 521 - vals - if not `NULL`, the numerical values 522 523 Level: advanced 524 525 Notes: 526 This routine is provided for people who need to have direct access 527 to the structure of a matrix. We hope that we provide enough 528 high-level matrix routines that few users will need it. 529 530 `MatGetRow()` always returns 0-based column indices, regardless of 531 whether the internal representation is 0-based (default) or 1-based. 532 533 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 534 not wish to extract these quantities. 535 536 The user can only examine the values extracted with `MatGetRow()`; 537 the values CANNOT be altered. To change the matrix entries, one 538 must use `MatSetValues()`. 539 540 You can only have one call to `MatGetRow()` outstanding for a particular 541 matrix at a time, per processor. `MatGetRow()` can only obtain rows 542 associated with the given processor, it cannot get rows from the 543 other processors; for that we suggest using `MatCreateSubMatrices()`, then 544 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 545 is in the global number of rows. 546 547 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 548 549 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 550 551 Fortran Note: 552 The calling sequence is 553 .vb 554 MatGetRow(matrix,row,ncols,cols,values,ierr) 555 Mat matrix (input) 556 PetscInt row (input) 557 PetscInt ncols (output) 558 PetscInt cols(maxcols) (output) 559 PetscScalar values(maxcols) output 560 .ve 561 where maxcols >= maximum nonzeros in any row of the matrix. 562 563 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 564 @*/ 565 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 566 { 567 PetscInt incols; 568 569 PetscFunctionBegin; 570 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 571 PetscValidType(mat, 1); 572 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 573 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 574 MatCheckPreallocated(mat, 1); 575 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); 576 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 577 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 578 if (ncols) *ncols = incols; 579 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 580 PetscFunctionReturn(PETSC_SUCCESS); 581 } 582 583 /*@ 584 MatConjugate - replaces the matrix values with their complex conjugates 585 586 Logically Collective 587 588 Input Parameter: 589 . mat - the matrix 590 591 Level: advanced 592 593 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 594 @*/ 595 PetscErrorCode MatConjugate(Mat mat) 596 { 597 PetscFunctionBegin; 598 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 599 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 601 PetscUseTypeMethod(mat, conjugate); 602 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 603 } 604 PetscFunctionReturn(PETSC_SUCCESS); 605 } 606 607 /*@C 608 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 609 610 Not Collective 611 612 Input Parameters: 613 + mat - the matrix 614 . row - the row to get 615 . ncols - the number of nonzeros 616 . cols - the columns of the nonzeros 617 - vals - if nonzero the column values 618 619 Level: advanced 620 621 Notes: 622 This routine should be called after you have finished examining the entries. 623 624 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 625 us of the array after it has been restored. If you pass `NULL`, it will 626 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 627 628 Fortran Note: 629 `MatRestoreRow()` MUST be called after `MatGetRow()` 630 before another call to `MatGetRow()` can be made. 631 632 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 633 @*/ 634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 638 if (ncols) PetscAssertPointer(ncols, 3); 639 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 640 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 641 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 642 if (ncols) *ncols = 0; 643 if (cols) *cols = NULL; 644 if (vals) *vals = NULL; 645 PetscFunctionReturn(PETSC_SUCCESS); 646 } 647 648 /*@ 649 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 650 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 651 652 Not Collective 653 654 Input Parameter: 655 . mat - the matrix 656 657 Level: advanced 658 659 Note: 660 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. 661 662 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 663 @*/ 664 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 668 PetscValidType(mat, 1); 669 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 670 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 671 MatCheckPreallocated(mat, 1); 672 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 673 PetscUseTypeMethod(mat, getrowuppertriangular); 674 PetscFunctionReturn(PETSC_SUCCESS); 675 } 676 677 /*@ 678 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 701 PetscUseTypeMethod(mat, restorerowuppertriangular); 702 PetscFunctionReturn(PETSC_SUCCESS); 703 } 704 705 /*@ 706 MatSetOptionsPrefix - Sets the prefix used for searching for all 707 `Mat` options in the database. 708 709 Logically Collective 710 711 Input Parameters: 712 + A - the matrix 713 - prefix - the prefix to prepend to all option names 714 715 Level: advanced 716 717 Notes: 718 A hyphen (-) must NOT be given at the beginning of the prefix name. 719 The first character of all runtime options is AUTOMATICALLY the hyphen. 720 721 This is NOT used for options for the factorization of the matrix. Normally the 722 prefix is automatically passed in from the PC calling the factorization. To set 723 it directly use `MatSetOptionsPrefixFactor()` 724 725 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 726 @*/ 727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 728 { 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 731 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@ 736 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 737 for matrices created with `MatGetFactor()` 738 739 Logically Collective 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names for the factored matrix 744 745 Level: developer 746 747 Notes: 748 A hyphen (-) must NOT be given at the beginning of the prefix name. 749 The first character of all runtime options is AUTOMATICALLY the hyphen. 750 751 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 752 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 753 754 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 755 @*/ 756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 757 { 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 760 if (prefix) { 761 PetscAssertPointer(prefix, 2); 762 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 763 if (prefix != A->factorprefix) { 764 PetscCall(PetscFree(A->factorprefix)); 765 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 766 } 767 } else PetscCall(PetscFree(A->factorprefix)); 768 PetscFunctionReturn(PETSC_SUCCESS); 769 } 770 771 /*@ 772 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 773 for matrices created with `MatGetFactor()` 774 775 Logically Collective 776 777 Input Parameters: 778 + A - the matrix 779 - prefix - the prefix to prepend to all option names for the factored matrix 780 781 Level: developer 782 783 Notes: 784 A hyphen (-) must NOT be given at the beginning of the prefix name. 785 The first character of all runtime options is AUTOMATICALLY the hyphen. 786 787 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 788 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 789 790 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 791 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 792 `MatSetOptionsPrefix()` 793 @*/ 794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 795 { 796 size_t len1, len2, new_len; 797 798 PetscFunctionBegin; 799 PetscValidHeader(A, 1); 800 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 801 if (!A->factorprefix) { 802 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 803 PetscFunctionReturn(PETSC_SUCCESS); 804 } 805 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 806 807 PetscCall(PetscStrlen(A->factorprefix, &len1)); 808 PetscCall(PetscStrlen(prefix, &len2)); 809 new_len = len1 + len2 + 1; 810 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 811 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 812 PetscFunctionReturn(PETSC_SUCCESS); 813 } 814 815 /*@ 816 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 817 matrix options in the database. 818 819 Logically Collective 820 821 Input Parameters: 822 + A - the matrix 823 - prefix - the prefix to prepend to all option names 824 825 Level: advanced 826 827 Note: 828 A hyphen (-) must NOT be given at the beginning of the prefix name. 829 The first character of all runtime options is AUTOMATICALLY the hyphen. 830 831 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 832 @*/ 833 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 834 { 835 PetscFunctionBegin; 836 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 837 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@ 842 MatGetOptionsPrefix - Gets the prefix used for searching for all 843 matrix options in the database. 844 845 Not Collective 846 847 Input Parameter: 848 . A - the matrix 849 850 Output Parameter: 851 . prefix - pointer to the prefix string used 852 853 Level: advanced 854 855 Fortran Note: 856 The user should pass in a string `prefix` of 857 sufficient length to hold the prefix. 858 859 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 860 @*/ 861 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 862 { 863 PetscFunctionBegin; 864 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 865 PetscAssertPointer(prefix, 2); 866 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 867 PetscFunctionReturn(PETSC_SUCCESS); 868 } 869 870 /*@ 871 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 872 873 Not Collective 874 875 Input Parameter: 876 . A - the matrix 877 878 Output Parameter: 879 . state - the object state 880 881 Level: advanced 882 883 Note: 884 Object state is an integer which gets increased every time 885 the object is changed. By saving and later querying the object state 886 one can determine whether information about the object is still current. 887 888 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 889 890 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 891 @*/ 892 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 893 { 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 896 PetscAssertPointer(state, 2); 897 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 898 PetscFunctionReturn(PETSC_SUCCESS); 899 } 900 901 /*@ 902 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 903 904 Collective 905 906 Input Parameter: 907 . A - the matrix 908 909 Level: beginner 910 911 Notes: 912 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 913 914 Users can reset the preallocation to access the original memory. 915 916 Currently only supported for `MATAIJ` matrices. 917 918 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 919 @*/ 920 PetscErrorCode MatResetPreallocation(Mat A) 921 { 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 924 PetscValidType(A, 1); 925 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 926 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 927 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 928 PetscFunctionReturn(PETSC_SUCCESS); 929 } 930 931 /*@ 932 MatSetUp - Sets up the internal matrix data structures for later use. 933 934 Collective 935 936 Input Parameter: 937 . A - the matrix 938 939 Level: intermediate 940 941 Notes: 942 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 943 setting values in the matrix. 944 945 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 946 947 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 948 @*/ 949 PetscErrorCode MatSetUp(Mat A) 950 { 951 PetscFunctionBegin; 952 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 953 if (!((PetscObject)A)->type_name) { 954 PetscMPIInt size; 955 956 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 957 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 958 } 959 if (!A->preallocated) PetscTryTypeMethod(A, setup); 960 PetscCall(PetscLayoutSetUp(A->rmap)); 961 PetscCall(PetscLayoutSetUp(A->cmap)); 962 A->preallocated = PETSC_TRUE; 963 PetscFunctionReturn(PETSC_SUCCESS); 964 } 965 966 #if defined(PETSC_HAVE_SAWS) 967 #include <petscviewersaws.h> 968 #endif 969 970 /* 971 If threadsafety is on extraneous matrices may be printed 972 973 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 974 */ 975 #if !defined(PETSC_HAVE_THREADSAFETY) 976 static PetscInt insidematview = 0; 977 #endif 978 979 /*@ 980 MatViewFromOptions - View properties of the matrix based on options set in the options database 981 982 Collective 983 984 Input Parameters: 985 + A - the matrix 986 . obj - optional additional object that provides the options prefix to use 987 - name - command line option 988 989 Options Database Key: 990 . -mat_view [viewertype]:... - the viewer and its options 991 992 Level: intermediate 993 994 Note: 995 .vb 996 If no value is provided ascii:stdout is used 997 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 998 for example ascii::ascii_info prints just the information about the object not all details 999 unless :append is given filename opens in write mode, overwriting what was already there 1000 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1001 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1002 socket[:port] defaults to the standard output port 1003 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1004 .ve 1005 1006 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1007 @*/ 1008 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1009 { 1010 PetscFunctionBegin; 1011 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1012 #if !defined(PETSC_HAVE_THREADSAFETY) 1013 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1014 #endif 1015 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1016 PetscFunctionReturn(PETSC_SUCCESS); 1017 } 1018 1019 /*@ 1020 MatView - display information about a matrix in a variety ways 1021 1022 Collective on viewer 1023 1024 Input Parameters: 1025 + mat - the matrix 1026 - viewer - visualization context 1027 1028 Options Database Keys: 1029 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1030 . -mat_view ::ascii_info_detail - Prints more detailed info 1031 . -mat_view - Prints matrix in ASCII format 1032 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1033 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1034 . -display <name> - Sets display name (default is host) 1035 . -draw_pause <sec> - Sets number of seconds to pause after display 1036 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1037 . -viewer_socket_machine <machine> - - 1038 . -viewer_socket_port <port> - - 1039 . -mat_view binary - save matrix to file in binary format 1040 - -viewer_binary_filename <name> - - 1041 1042 Level: beginner 1043 1044 Notes: 1045 The available visualization contexts include 1046 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1047 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1048 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1049 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1050 1051 The user can open alternative visualization contexts with 1052 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1053 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1054 specified file; corresponding input uses `MatLoad()` 1055 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1056 an X window display 1057 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1058 Currently only the `MATSEQDENSE` and `MATAIJ` 1059 matrix types support the Socket viewer. 1060 1061 The user can call `PetscViewerPushFormat()` to specify the output 1062 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1063 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1064 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1065 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1066 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1067 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1068 format common among all matrix types 1069 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1070 format (which is in many cases the same as the default) 1071 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1072 size and structure (not the matrix entries) 1073 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1074 the matrix structure 1075 1076 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1077 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1078 1079 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1080 1081 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1082 viewer is used. 1083 1084 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1085 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1086 1087 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1088 and then use the following mouse functions. 1089 .vb 1090 left mouse: zoom in 1091 middle mouse: zoom out 1092 right mouse: continue with the simulation 1093 .ve 1094 1095 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1096 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1097 @*/ 1098 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1099 { 1100 PetscInt rows, cols, rbs, cbs; 1101 PetscBool isascii, isstring, issaws; 1102 PetscViewerFormat format; 1103 PetscMPIInt size; 1104 1105 PetscFunctionBegin; 1106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1107 PetscValidType(mat, 1); 1108 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1109 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1110 1111 PetscCall(PetscViewerGetFormat(viewer, &format)); 1112 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1113 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1114 1115 #if !defined(PETSC_HAVE_THREADSAFETY) 1116 insidematview++; 1117 #endif 1118 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1119 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1120 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1121 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"); 1122 1123 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1124 if (isascii) { 1125 if (!mat->preallocated) { 1126 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1127 #if !defined(PETSC_HAVE_THREADSAFETY) 1128 insidematview--; 1129 #endif 1130 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1131 PetscFunctionReturn(PETSC_SUCCESS); 1132 } 1133 if (!mat->assembled) { 1134 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1135 #if !defined(PETSC_HAVE_THREADSAFETY) 1136 insidematview--; 1137 #endif 1138 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1139 PetscFunctionReturn(PETSC_SUCCESS); 1140 } 1141 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1142 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1143 MatNullSpace nullsp, transnullsp; 1144 1145 PetscCall(PetscViewerASCIIPushTab(viewer)); 1146 PetscCall(MatGetSize(mat, &rows, &cols)); 1147 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1148 if (rbs != 1 || cbs != 1) { 1149 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" : "")); 1150 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1151 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1152 if (mat->factortype) { 1153 MatSolverType solver; 1154 PetscCall(MatFactorGetSolverType(mat, &solver)); 1155 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1156 } 1157 if (mat->ops->getinfo) { 1158 MatInfo info; 1159 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1160 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1161 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1162 } 1163 PetscCall(MatGetNullSpace(mat, &nullsp)); 1164 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1165 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1166 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1167 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1168 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1169 PetscCall(PetscViewerASCIIPushTab(viewer)); 1170 PetscCall(MatProductView(mat, viewer)); 1171 PetscCall(PetscViewerASCIIPopTab(viewer)); 1172 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1173 IS tmp; 1174 1175 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1176 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1177 PetscCall(PetscViewerASCIIPushTab(viewer)); 1178 PetscCall(ISView(tmp, viewer)); 1179 PetscCall(PetscViewerASCIIPopTab(viewer)); 1180 PetscCall(ISDestroy(&tmp)); 1181 } 1182 } 1183 } else if (issaws) { 1184 #if defined(PETSC_HAVE_SAWS) 1185 PetscMPIInt rank; 1186 1187 PetscCall(PetscObjectName((PetscObject)mat)); 1188 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1189 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1190 #endif 1191 } else if (isstring) { 1192 const char *type; 1193 PetscCall(MatGetType(mat, &type)); 1194 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1195 PetscTryTypeMethod(mat, view, viewer); 1196 } 1197 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1198 PetscCall(PetscViewerASCIIPushTab(viewer)); 1199 PetscUseTypeMethod(mat, viewnative, viewer); 1200 PetscCall(PetscViewerASCIIPopTab(viewer)); 1201 } else if (mat->ops->view) { 1202 PetscCall(PetscViewerASCIIPushTab(viewer)); 1203 PetscUseTypeMethod(mat, view, viewer); 1204 PetscCall(PetscViewerASCIIPopTab(viewer)); 1205 } 1206 if (isascii) { 1207 PetscCall(PetscViewerGetFormat(viewer, &format)); 1208 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1209 } 1210 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1211 #if !defined(PETSC_HAVE_THREADSAFETY) 1212 insidematview--; 1213 #endif 1214 PetscFunctionReturn(PETSC_SUCCESS); 1215 } 1216 1217 #if defined(PETSC_USE_DEBUG) 1218 #include <../src/sys/totalview/tv_data_display.h> 1219 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1220 { 1221 TV_add_row("Local rows", "int", &mat->rmap->n); 1222 TV_add_row("Local columns", "int", &mat->cmap->n); 1223 TV_add_row("Global rows", "int", &mat->rmap->N); 1224 TV_add_row("Global columns", "int", &mat->cmap->N); 1225 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1226 return TV_format_OK; 1227 } 1228 #endif 1229 1230 /*@ 1231 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1232 with `MatView()`. The matrix format is determined from the options database. 1233 Generates a parallel MPI matrix if the communicator has more than one 1234 processor. The default matrix type is `MATAIJ`. 1235 1236 Collective 1237 1238 Input Parameters: 1239 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1240 or some related function before a call to `MatLoad()` 1241 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1242 1243 Options Database Key: 1244 . -matload_block_size <bs> - set block size 1245 1246 Level: beginner 1247 1248 Notes: 1249 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1250 `Mat` before calling this routine if you wish to set it from the options database. 1251 1252 `MatLoad()` automatically loads into the options database any options 1253 given in the file filename.info where filename is the name of the file 1254 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1255 file will be ignored if you use the -viewer_binary_skip_info option. 1256 1257 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1258 sets the default matrix type AIJ and sets the local and global sizes. 1259 If type and/or size is already set, then the same are used. 1260 1261 In parallel, each processor can load a subset of rows (or the 1262 entire matrix). This routine is especially useful when a large 1263 matrix is stored on disk and only part of it is desired on each 1264 processor. For example, a parallel solver may access only some of 1265 the rows from each processor. The algorithm used here reads 1266 relatively small blocks of data rather than reading the entire 1267 matrix and then subsetting it. 1268 1269 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1270 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1271 or the sequence like 1272 .vb 1273 `PetscViewer` v; 1274 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1275 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1276 `PetscViewerSetFromOptions`(v); 1277 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1278 `PetscViewerFileSetName`(v,"datafile"); 1279 .ve 1280 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1281 $ -viewer_type {binary, hdf5} 1282 1283 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1284 and src/mat/tutorials/ex10.c with the second approach. 1285 1286 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1287 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1288 Multiple objects, both matrices and vectors, can be stored within the same file. 1289 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1290 1291 Most users should not need to know the details of the binary storage 1292 format, since `MatLoad()` and `MatView()` completely hide these details. 1293 But for anyone who is interested, the standard binary matrix storage 1294 format is 1295 1296 .vb 1297 PetscInt MAT_FILE_CLASSID 1298 PetscInt number of rows 1299 PetscInt number of columns 1300 PetscInt total number of nonzeros 1301 PetscInt *number nonzeros in each row 1302 PetscInt *column indices of all nonzeros (starting index is zero) 1303 PetscScalar *values of all nonzeros 1304 .ve 1305 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1306 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 1307 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1308 1309 PETSc automatically does the byte swapping for 1310 machines that store the bytes reversed. Thus if you write your own binary 1311 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1312 and `PetscBinaryWrite()` to see how this may be done. 1313 1314 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1315 Each processor's chunk is loaded independently by its owning MPI process. 1316 Multiple objects, both matrices and vectors, can be stored within the same file. 1317 They are looked up by their PetscObject name. 1318 1319 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1320 by default the same structure and naming of the AIJ arrays and column count 1321 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1322 $ save example.mat A b -v7.3 1323 can be directly read by this routine (see Reference 1 for details). 1324 1325 Depending on your MATLAB version, this format might be a default, 1326 otherwise you can set it as default in Preferences. 1327 1328 Unless -nocompression flag is used to save the file in MATLAB, 1329 PETSc must be configured with ZLIB package. 1330 1331 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1332 1333 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1334 1335 Corresponding `MatView()` is not yet implemented. 1336 1337 The loaded matrix is actually a transpose of the original one in MATLAB, 1338 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1339 With this format, matrix is automatically transposed by PETSc, 1340 unless the matrix is marked as SPD or symmetric 1341 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1342 1343 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1344 1345 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1346 @*/ 1347 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1348 { 1349 PetscBool flg; 1350 1351 PetscFunctionBegin; 1352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1353 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1354 1355 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1356 1357 flg = PETSC_FALSE; 1358 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1359 if (flg) { 1360 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1361 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1362 } 1363 flg = PETSC_FALSE; 1364 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1365 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1366 1367 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1368 PetscUseTypeMethod(mat, load, viewer); 1369 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1370 PetscFunctionReturn(PETSC_SUCCESS); 1371 } 1372 1373 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1374 { 1375 Mat_Redundant *redund = *redundant; 1376 1377 PetscFunctionBegin; 1378 if (redund) { 1379 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1380 PetscCall(ISDestroy(&redund->isrow)); 1381 PetscCall(ISDestroy(&redund->iscol)); 1382 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1383 } else { 1384 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1385 PetscCall(PetscFree(redund->sbuf_j)); 1386 PetscCall(PetscFree(redund->sbuf_a)); 1387 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1388 PetscCall(PetscFree(redund->rbuf_j[i])); 1389 PetscCall(PetscFree(redund->rbuf_a[i])); 1390 } 1391 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1392 } 1393 1394 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1395 PetscCall(PetscFree(redund)); 1396 } 1397 PetscFunctionReturn(PETSC_SUCCESS); 1398 } 1399 1400 /*@ 1401 MatDestroy - Frees space taken by a matrix. 1402 1403 Collective 1404 1405 Input Parameter: 1406 . A - the matrix 1407 1408 Level: beginner 1409 1410 Developer Note: 1411 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1412 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1413 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1414 if changes are needed here. 1415 1416 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1417 @*/ 1418 PetscErrorCode MatDestroy(Mat *A) 1419 { 1420 PetscFunctionBegin; 1421 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1422 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1423 if (--((PetscObject)*A)->refct > 0) { 1424 *A = NULL; 1425 PetscFunctionReturn(PETSC_SUCCESS); 1426 } 1427 1428 /* if memory was published with SAWs then destroy it */ 1429 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1430 PetscTryTypeMethod(*A, destroy); 1431 1432 PetscCall(PetscFree((*A)->factorprefix)); 1433 PetscCall(PetscFree((*A)->defaultvectype)); 1434 PetscCall(PetscFree((*A)->defaultrandtype)); 1435 PetscCall(PetscFree((*A)->bsizes)); 1436 PetscCall(PetscFree((*A)->solvertype)); 1437 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1438 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1439 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1440 PetscCall(MatProductClear(*A)); 1441 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1442 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1443 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1444 PetscCall(MatDestroy(&(*A)->schur)); 1445 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1446 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1447 PetscCall(PetscHeaderDestroy(A)); 1448 PetscFunctionReturn(PETSC_SUCCESS); 1449 } 1450 1451 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1452 /*@ 1453 MatSetValues - Inserts or adds a block of values into a matrix. 1454 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1455 MUST be called after all calls to `MatSetValues()` have been completed. 1456 1457 Not Collective 1458 1459 Input Parameters: 1460 + mat - the matrix 1461 . v - a logically two-dimensional array of values 1462 . m - the number of rows 1463 . idxm - the global indices of the rows 1464 . n - the number of columns 1465 . idxn - the global indices of the columns 1466 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1467 1468 Level: beginner 1469 1470 Notes: 1471 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1472 1473 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1474 options cannot be mixed without intervening calls to the assembly 1475 routines. 1476 1477 `MatSetValues()` uses 0-based row and column numbers in Fortran 1478 as well as in C. 1479 1480 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1481 simply ignored. This allows easily inserting element stiffness matrices 1482 with homogeneous Dirichlet boundary conditions that you don't want represented 1483 in the matrix. 1484 1485 Efficiency Alert: 1486 The routine `MatSetValuesBlocked()` may offer much better efficiency 1487 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1488 1489 Fortran Notes: 1490 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1491 .vb 1492 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1493 .ve 1494 1495 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1496 1497 Developer Note: 1498 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1499 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1500 1501 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1502 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1503 @*/ 1504 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1505 { 1506 PetscFunctionBeginHot; 1507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1508 PetscValidType(mat, 1); 1509 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1510 PetscAssertPointer(idxm, 3); 1511 PetscAssertPointer(idxn, 5); 1512 MatCheckPreallocated(mat, 1); 1513 1514 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1515 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1516 1517 if (PetscDefined(USE_DEBUG)) { 1518 PetscInt i, j; 1519 1520 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1521 if (v) { 1522 for (i = 0; i < m; i++) { 1523 for (j = 0; j < n; j++) { 1524 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1525 #if defined(PETSC_USE_COMPLEX) 1526 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]); 1527 #else 1528 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]); 1529 #endif 1530 } 1531 } 1532 } 1533 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); 1534 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); 1535 } 1536 1537 if (mat->assembled) { 1538 mat->was_assembled = PETSC_TRUE; 1539 mat->assembled = PETSC_FALSE; 1540 } 1541 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1542 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1543 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1544 PetscFunctionReturn(PETSC_SUCCESS); 1545 } 1546 1547 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1548 /*@ 1549 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1550 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1551 MUST be called after all calls to `MatSetValues()` have been completed. 1552 1553 Not Collective 1554 1555 Input Parameters: 1556 + mat - the matrix 1557 . v - a logically two-dimensional array of values 1558 . ism - the rows to provide 1559 . isn - the columns to provide 1560 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1561 1562 Level: beginner 1563 1564 Notes: 1565 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1566 1567 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1568 options cannot be mixed without intervening calls to the assembly 1569 routines. 1570 1571 `MatSetValues()` uses 0-based row and column numbers in Fortran 1572 as well as in C. 1573 1574 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1575 simply ignored. This allows easily inserting element stiffness matrices 1576 with homogeneous Dirichlet boundary conditions that you don't want represented 1577 in the matrix. 1578 1579 Efficiency Alert: 1580 The routine `MatSetValuesBlocked()` may offer much better efficiency 1581 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1582 1583 This is currently not optimized for any particular `ISType` 1584 1585 Developer Note: 1586 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1587 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1588 1589 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1590 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1591 @*/ 1592 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1593 { 1594 PetscInt m, n; 1595 const PetscInt *rows, *cols; 1596 1597 PetscFunctionBeginHot; 1598 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1599 PetscCall(ISGetIndices(ism, &rows)); 1600 PetscCall(ISGetIndices(isn, &cols)); 1601 PetscCall(ISGetLocalSize(ism, &m)); 1602 PetscCall(ISGetLocalSize(isn, &n)); 1603 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1604 PetscCall(ISRestoreIndices(ism, &rows)); 1605 PetscCall(ISRestoreIndices(isn, &cols)); 1606 PetscFunctionReturn(PETSC_SUCCESS); 1607 } 1608 1609 /*@ 1610 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1611 values into a matrix 1612 1613 Not Collective 1614 1615 Input Parameters: 1616 + mat - the matrix 1617 . row - the (block) row to set 1618 - v - a logically two-dimensional array of values 1619 1620 Level: intermediate 1621 1622 Notes: 1623 The values, `v`, are column-oriented (for the block version) and sorted 1624 1625 All the nonzero values in `row` must be provided 1626 1627 The matrix must have previously had its column indices set, likely by having been assembled. 1628 1629 `row` must belong to this MPI process 1630 1631 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1632 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1633 @*/ 1634 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1635 { 1636 PetscInt globalrow; 1637 1638 PetscFunctionBegin; 1639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1640 PetscValidType(mat, 1); 1641 PetscAssertPointer(v, 3); 1642 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1643 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1644 PetscFunctionReturn(PETSC_SUCCESS); 1645 } 1646 1647 /*@ 1648 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1649 values into a matrix 1650 1651 Not Collective 1652 1653 Input Parameters: 1654 + mat - the matrix 1655 . row - the (block) row to set 1656 - 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 1657 1658 Level: advanced 1659 1660 Notes: 1661 The values, `v`, are column-oriented for the block version. 1662 1663 All the nonzeros in `row` must be provided 1664 1665 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1666 1667 `row` must belong to this process 1668 1669 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1670 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1671 @*/ 1672 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1673 { 1674 PetscFunctionBeginHot; 1675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1676 PetscValidType(mat, 1); 1677 MatCheckPreallocated(mat, 1); 1678 PetscAssertPointer(v, 3); 1679 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1680 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1681 mat->insertmode = INSERT_VALUES; 1682 1683 if (mat->assembled) { 1684 mat->was_assembled = PETSC_TRUE; 1685 mat->assembled = PETSC_FALSE; 1686 } 1687 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1688 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1689 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1690 PetscFunctionReturn(PETSC_SUCCESS); 1691 } 1692 1693 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1694 /*@ 1695 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1696 Using structured grid indexing 1697 1698 Not Collective 1699 1700 Input Parameters: 1701 + mat - the matrix 1702 . m - number of rows being entered 1703 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1704 . n - number of columns being entered 1705 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1706 . v - a logically two-dimensional array of values 1707 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1708 1709 Level: beginner 1710 1711 Notes: 1712 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1713 1714 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1715 options cannot be mixed without intervening calls to the assembly 1716 routines. 1717 1718 The grid coordinates are across the entire grid, not just the local portion 1719 1720 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1721 as well as in C. 1722 1723 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1724 1725 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1726 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1727 1728 The columns and rows in the stencil passed in MUST be contained within the 1729 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1730 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1731 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1732 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1733 1734 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1735 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1736 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1737 `DM_BOUNDARY_PERIODIC` boundary type. 1738 1739 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 1740 a single value per point) you can skip filling those indices. 1741 1742 Inspired by the structured grid interface to the HYPRE package 1743 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1744 1745 Efficiency Alert: 1746 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1747 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1748 1749 Fortran Note: 1750 `idxm` and `idxn` should be declared as 1751 $ MatStencil idxm(4,m),idxn(4,n) 1752 and the values inserted using 1753 .vb 1754 idxm(MatStencil_i,1) = i 1755 idxm(MatStencil_j,1) = j 1756 idxm(MatStencil_k,1) = k 1757 idxm(MatStencil_c,1) = c 1758 etc 1759 .ve 1760 1761 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1762 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1763 @*/ 1764 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1765 { 1766 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1767 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1768 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1769 1770 PetscFunctionBegin; 1771 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1772 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1773 PetscValidType(mat, 1); 1774 PetscAssertPointer(idxm, 3); 1775 PetscAssertPointer(idxn, 5); 1776 1777 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1778 jdxm = buf; 1779 jdxn = buf + m; 1780 } else { 1781 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1782 jdxm = bufm; 1783 jdxn = bufn; 1784 } 1785 for (i = 0; i < m; i++) { 1786 for (j = 0; j < 3 - sdim; j++) dxm++; 1787 tmp = *dxm++ - starts[0]; 1788 for (j = 0; j < dim - 1; j++) { 1789 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1790 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1791 } 1792 if (mat->stencil.noc) dxm++; 1793 jdxm[i] = tmp; 1794 } 1795 for (i = 0; i < n; i++) { 1796 for (j = 0; j < 3 - sdim; j++) dxn++; 1797 tmp = *dxn++ - starts[0]; 1798 for (j = 0; j < dim - 1; j++) { 1799 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1800 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1801 } 1802 if (mat->stencil.noc) dxn++; 1803 jdxn[i] = tmp; 1804 } 1805 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1806 PetscCall(PetscFree2(bufm, bufn)); 1807 PetscFunctionReturn(PETSC_SUCCESS); 1808 } 1809 1810 /*@ 1811 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1812 Using structured grid indexing 1813 1814 Not Collective 1815 1816 Input Parameters: 1817 + mat - the matrix 1818 . m - number of rows being entered 1819 . idxm - grid coordinates for matrix rows being entered 1820 . n - number of columns being entered 1821 . idxn - grid coordinates for matrix columns being entered 1822 . v - a logically two-dimensional array of values 1823 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1824 1825 Level: beginner 1826 1827 Notes: 1828 By default the values, `v`, are row-oriented and unsorted. 1829 See `MatSetOption()` for other options. 1830 1831 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1832 options cannot be mixed without intervening calls to the assembly 1833 routines. 1834 1835 The grid coordinates are across the entire grid, not just the local portion 1836 1837 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1838 as well as in C. 1839 1840 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1841 1842 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1843 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1844 1845 The columns and rows in the stencil passed in MUST be contained within the 1846 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1847 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1848 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1849 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1850 1851 Negative indices may be passed in idxm and idxn, these rows and columns are 1852 simply ignored. This allows easily inserting element stiffness matrices 1853 with homogeneous Dirichlet boundary conditions that you don't want represented 1854 in the matrix. 1855 1856 Inspired by the structured grid interface to the HYPRE package 1857 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1858 1859 Fortran Note: 1860 `idxm` and `idxn` should be declared as 1861 $ MatStencil idxm(4,m),idxn(4,n) 1862 and the values inserted using 1863 .vb 1864 idxm(MatStencil_i,1) = i 1865 idxm(MatStencil_j,1) = j 1866 idxm(MatStencil_k,1) = k 1867 etc 1868 .ve 1869 1870 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1871 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1872 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1873 @*/ 1874 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1875 { 1876 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1877 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1878 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1879 1880 PetscFunctionBegin; 1881 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1883 PetscValidType(mat, 1); 1884 PetscAssertPointer(idxm, 3); 1885 PetscAssertPointer(idxn, 5); 1886 PetscAssertPointer(v, 6); 1887 1888 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1889 jdxm = buf; 1890 jdxn = buf + m; 1891 } else { 1892 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1893 jdxm = bufm; 1894 jdxn = bufn; 1895 } 1896 for (i = 0; i < m; i++) { 1897 for (j = 0; j < 3 - sdim; j++) dxm++; 1898 tmp = *dxm++ - starts[0]; 1899 for (j = 0; j < sdim - 1; j++) { 1900 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1901 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1902 } 1903 dxm++; 1904 jdxm[i] = tmp; 1905 } 1906 for (i = 0; i < n; i++) { 1907 for (j = 0; j < 3 - sdim; j++) dxn++; 1908 tmp = *dxn++ - starts[0]; 1909 for (j = 0; j < sdim - 1; j++) { 1910 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1911 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1912 } 1913 dxn++; 1914 jdxn[i] = tmp; 1915 } 1916 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1917 PetscCall(PetscFree2(bufm, bufn)); 1918 PetscFunctionReturn(PETSC_SUCCESS); 1919 } 1920 1921 /*@ 1922 MatSetStencil - Sets the grid information for setting values into a matrix via 1923 `MatSetValuesStencil()` 1924 1925 Not Collective 1926 1927 Input Parameters: 1928 + mat - the matrix 1929 . dim - dimension of the grid 1, 2, or 3 1930 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1931 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1932 - dof - number of degrees of freedom per node 1933 1934 Level: beginner 1935 1936 Notes: 1937 Inspired by the structured grid interface to the HYPRE package 1938 (www.llnl.gov/CASC/hyper) 1939 1940 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1941 user. 1942 1943 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1944 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1945 @*/ 1946 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1947 { 1948 PetscFunctionBegin; 1949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1950 PetscAssertPointer(dims, 3); 1951 PetscAssertPointer(starts, 4); 1952 1953 mat->stencil.dim = dim + (dof > 1); 1954 for (PetscInt i = 0; i < dim; i++) { 1955 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1956 mat->stencil.starts[i] = starts[dim - i - 1]; 1957 } 1958 mat->stencil.dims[dim] = dof; 1959 mat->stencil.starts[dim] = 0; 1960 mat->stencil.noc = (PetscBool)(dof == 1); 1961 PetscFunctionReturn(PETSC_SUCCESS); 1962 } 1963 1964 /*@ 1965 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1966 1967 Not Collective 1968 1969 Input Parameters: 1970 + mat - the matrix 1971 . v - a logically two-dimensional array of values 1972 . m - the number of block rows 1973 . idxm - the global block indices 1974 . n - the number of block columns 1975 . idxn - the global block indices 1976 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1977 1978 Level: intermediate 1979 1980 Notes: 1981 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1982 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1983 1984 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1985 NOT the total number of rows/columns; for example, if the block size is 2 and 1986 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1987 The values in `idxm` would be 1 2; that is the first index for each block divided by 1988 the block size. 1989 1990 You must call `MatSetBlockSize()` when constructing this matrix (before 1991 preallocating it). 1992 1993 By default the values, `v`, are row-oriented, so the layout of 1994 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1995 1996 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1997 options cannot be mixed without intervening calls to the assembly 1998 routines. 1999 2000 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2001 as well as in C. 2002 2003 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2004 simply ignored. This allows easily inserting element stiffness matrices 2005 with homogeneous Dirichlet boundary conditions that you don't want represented 2006 in the matrix. 2007 2008 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2009 internal searching must be done to determine where to place the 2010 data in the matrix storage space. By instead inserting blocks of 2011 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2012 reduced. 2013 2014 Example: 2015 .vb 2016 Suppose m=n=2 and block size(bs) = 2 The array is 2017 2018 1 2 | 3 4 2019 5 6 | 7 8 2020 - - - | - - - 2021 9 10 | 11 12 2022 13 14 | 15 16 2023 2024 v[] should be passed in like 2025 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2026 2027 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2028 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2029 .ve 2030 2031 Fortran Notes: 2032 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2033 .vb 2034 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2035 .ve 2036 2037 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2038 2039 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2040 @*/ 2041 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2042 { 2043 PetscFunctionBeginHot; 2044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2045 PetscValidType(mat, 1); 2046 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2047 PetscAssertPointer(idxm, 3); 2048 PetscAssertPointer(idxn, 5); 2049 MatCheckPreallocated(mat, 1); 2050 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2051 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2052 if (PetscDefined(USE_DEBUG)) { 2053 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2054 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2055 } 2056 if (PetscDefined(USE_DEBUG)) { 2057 PetscInt rbs, cbs, M, N, i; 2058 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2059 PetscCall(MatGetSize(mat, &M, &N)); 2060 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); 2061 for (i = 0; i < n; i++) 2062 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); 2063 } 2064 if (mat->assembled) { 2065 mat->was_assembled = PETSC_TRUE; 2066 mat->assembled = PETSC_FALSE; 2067 } 2068 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2069 if (mat->ops->setvaluesblocked) { 2070 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2071 } else { 2072 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2073 PetscInt i, j, bs, cbs; 2074 2075 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2076 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2077 iidxm = buf; 2078 iidxn = buf + m * bs; 2079 } else { 2080 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2081 iidxm = bufr; 2082 iidxn = bufc; 2083 } 2084 for (i = 0; i < m; i++) { 2085 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2086 } 2087 if (m != n || bs != cbs || idxm != idxn) { 2088 for (i = 0; i < n; i++) { 2089 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2090 } 2091 } else iidxn = iidxm; 2092 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2093 PetscCall(PetscFree2(bufr, bufc)); 2094 } 2095 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2096 PetscFunctionReturn(PETSC_SUCCESS); 2097 } 2098 2099 /*@ 2100 MatGetValues - Gets a block of local values from a matrix. 2101 2102 Not Collective; can only return values that are owned by the give process 2103 2104 Input Parameters: 2105 + mat - the matrix 2106 . v - a logically two-dimensional array for storing the values 2107 . m - the number of rows 2108 . idxm - the global indices of the rows 2109 . n - the number of columns 2110 - idxn - the global indices of the columns 2111 2112 Level: advanced 2113 2114 Notes: 2115 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2116 The values, `v`, are then returned in a row-oriented format, 2117 analogous to that used by default in `MatSetValues()`. 2118 2119 `MatGetValues()` uses 0-based row and column numbers in 2120 Fortran as well as in C. 2121 2122 `MatGetValues()` requires that the matrix has been assembled 2123 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2124 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2125 without intermediate matrix assembly. 2126 2127 Negative row or column indices will be ignored and those locations in `v` will be 2128 left unchanged. 2129 2130 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2131 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2132 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2133 2134 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2135 @*/ 2136 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2137 { 2138 PetscFunctionBegin; 2139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2140 PetscValidType(mat, 1); 2141 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2142 PetscAssertPointer(idxm, 3); 2143 PetscAssertPointer(idxn, 5); 2144 PetscAssertPointer(v, 6); 2145 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2146 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2147 MatCheckPreallocated(mat, 1); 2148 2149 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2150 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2151 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2152 PetscFunctionReturn(PETSC_SUCCESS); 2153 } 2154 2155 /*@ 2156 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2157 defined previously by `MatSetLocalToGlobalMapping()` 2158 2159 Not Collective 2160 2161 Input Parameters: 2162 + mat - the matrix 2163 . nrow - number of rows 2164 . irow - the row local indices 2165 . ncol - number of columns 2166 - icol - the column local indices 2167 2168 Output Parameter: 2169 . y - a logically two-dimensional array of values 2170 2171 Level: advanced 2172 2173 Notes: 2174 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2175 2176 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, 2177 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2178 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2179 with `MatSetLocalToGlobalMapping()`. 2180 2181 Developer Note: 2182 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2183 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2184 2185 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2186 `MatSetValuesLocal()`, `MatGetValues()` 2187 @*/ 2188 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2189 { 2190 PetscFunctionBeginHot; 2191 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2192 PetscValidType(mat, 1); 2193 MatCheckPreallocated(mat, 1); 2194 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2195 PetscAssertPointer(irow, 3); 2196 PetscAssertPointer(icol, 5); 2197 if (PetscDefined(USE_DEBUG)) { 2198 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2199 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2200 } 2201 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2202 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2203 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2204 else { 2205 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2206 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2207 irowm = buf; 2208 icolm = buf + nrow; 2209 } else { 2210 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2211 irowm = bufr; 2212 icolm = bufc; 2213 } 2214 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2215 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2216 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2217 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2218 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2219 PetscCall(PetscFree2(bufr, bufc)); 2220 } 2221 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2222 PetscFunctionReturn(PETSC_SUCCESS); 2223 } 2224 2225 /*@ 2226 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2227 the same size. Currently, this can only be called once and creates the given matrix. 2228 2229 Not Collective 2230 2231 Input Parameters: 2232 + mat - the matrix 2233 . nb - the number of blocks 2234 . bs - the number of rows (and columns) in each block 2235 . rows - a concatenation of the rows for each block 2236 - v - a concatenation of logically two-dimensional arrays of values 2237 2238 Level: advanced 2239 2240 Notes: 2241 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2242 2243 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2244 2245 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2246 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2247 @*/ 2248 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2249 { 2250 PetscFunctionBegin; 2251 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2252 PetscValidType(mat, 1); 2253 PetscAssertPointer(rows, 4); 2254 PetscAssertPointer(v, 5); 2255 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2256 2257 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2258 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2259 else { 2260 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2261 } 2262 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2263 PetscFunctionReturn(PETSC_SUCCESS); 2264 } 2265 2266 /*@ 2267 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2268 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2269 using a local (per-processor) numbering. 2270 2271 Not Collective 2272 2273 Input Parameters: 2274 + x - the matrix 2275 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2276 - cmapping - column mapping 2277 2278 Level: intermediate 2279 2280 Note: 2281 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2282 2283 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2284 @*/ 2285 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2286 { 2287 PetscFunctionBegin; 2288 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2289 PetscValidType(x, 1); 2290 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2291 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2292 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2293 else { 2294 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2295 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2296 } 2297 PetscFunctionReturn(PETSC_SUCCESS); 2298 } 2299 2300 /*@ 2301 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2302 2303 Not Collective 2304 2305 Input Parameter: 2306 . A - the matrix 2307 2308 Output Parameters: 2309 + rmapping - row mapping 2310 - cmapping - column mapping 2311 2312 Level: advanced 2313 2314 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2315 @*/ 2316 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2317 { 2318 PetscFunctionBegin; 2319 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2320 PetscValidType(A, 1); 2321 if (rmapping) { 2322 PetscAssertPointer(rmapping, 2); 2323 *rmapping = A->rmap->mapping; 2324 } 2325 if (cmapping) { 2326 PetscAssertPointer(cmapping, 3); 2327 *cmapping = A->cmap->mapping; 2328 } 2329 PetscFunctionReturn(PETSC_SUCCESS); 2330 } 2331 2332 /*@ 2333 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2334 2335 Logically Collective 2336 2337 Input Parameters: 2338 + A - the matrix 2339 . rmap - row layout 2340 - cmap - column layout 2341 2342 Level: advanced 2343 2344 Note: 2345 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2346 2347 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2348 @*/ 2349 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2350 { 2351 PetscFunctionBegin; 2352 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2353 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2354 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2355 PetscFunctionReturn(PETSC_SUCCESS); 2356 } 2357 2358 /*@ 2359 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2360 2361 Not Collective 2362 2363 Input Parameter: 2364 . A - the matrix 2365 2366 Output Parameters: 2367 + rmap - row layout 2368 - cmap - column layout 2369 2370 Level: advanced 2371 2372 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2373 @*/ 2374 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2375 { 2376 PetscFunctionBegin; 2377 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2378 PetscValidType(A, 1); 2379 if (rmap) { 2380 PetscAssertPointer(rmap, 2); 2381 *rmap = A->rmap; 2382 } 2383 if (cmap) { 2384 PetscAssertPointer(cmap, 3); 2385 *cmap = A->cmap; 2386 } 2387 PetscFunctionReturn(PETSC_SUCCESS); 2388 } 2389 2390 /*@ 2391 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2392 using a local numbering of the rows and columns. 2393 2394 Not Collective 2395 2396 Input Parameters: 2397 + mat - the matrix 2398 . nrow - number of rows 2399 . irow - the row local indices 2400 . ncol - number of columns 2401 . icol - the column local indices 2402 . y - a logically two-dimensional array of values 2403 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2404 2405 Level: intermediate 2406 2407 Notes: 2408 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2409 2410 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2411 options cannot be mixed without intervening calls to the assembly 2412 routines. 2413 2414 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2415 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2416 2417 Fortran Notes: 2418 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2419 .vb 2420 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2421 .ve 2422 2423 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2424 2425 Developer Note: 2426 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2427 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2428 2429 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2430 `MatGetValuesLocal()` 2431 @*/ 2432 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2433 { 2434 PetscFunctionBeginHot; 2435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2436 PetscValidType(mat, 1); 2437 MatCheckPreallocated(mat, 1); 2438 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2439 PetscAssertPointer(irow, 3); 2440 PetscAssertPointer(icol, 5); 2441 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2442 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2443 if (PetscDefined(USE_DEBUG)) { 2444 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2445 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2446 } 2447 2448 if (mat->assembled) { 2449 mat->was_assembled = PETSC_TRUE; 2450 mat->assembled = PETSC_FALSE; 2451 } 2452 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2453 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2454 else { 2455 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2456 const PetscInt *irowm, *icolm; 2457 2458 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2459 bufr = buf; 2460 bufc = buf + nrow; 2461 irowm = bufr; 2462 icolm = bufc; 2463 } else { 2464 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2465 irowm = bufr; 2466 icolm = bufc; 2467 } 2468 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2469 else irowm = irow; 2470 if (mat->cmap->mapping) { 2471 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2472 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2473 } else icolm = irowm; 2474 } else icolm = icol; 2475 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2476 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2477 } 2478 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2479 PetscFunctionReturn(PETSC_SUCCESS); 2480 } 2481 2482 /*@ 2483 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2484 using a local ordering of the nodes a block at a time. 2485 2486 Not Collective 2487 2488 Input Parameters: 2489 + mat - the matrix 2490 . nrow - number of rows 2491 . irow - the row local indices 2492 . ncol - number of columns 2493 . icol - the column local indices 2494 . y - a logically two-dimensional array of values 2495 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2496 2497 Level: intermediate 2498 2499 Notes: 2500 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2501 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2502 2503 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2504 options cannot be mixed without intervening calls to the assembly 2505 routines. 2506 2507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2508 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2509 2510 Fortran Notes: 2511 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2512 .vb 2513 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2514 .ve 2515 2516 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2517 2518 Developer Note: 2519 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2520 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2521 2522 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2523 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2524 @*/ 2525 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2526 { 2527 PetscFunctionBeginHot; 2528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2529 PetscValidType(mat, 1); 2530 MatCheckPreallocated(mat, 1); 2531 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2532 PetscAssertPointer(irow, 3); 2533 PetscAssertPointer(icol, 5); 2534 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2535 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2536 if (PetscDefined(USE_DEBUG)) { 2537 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2538 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); 2539 } 2540 2541 if (mat->assembled) { 2542 mat->was_assembled = PETSC_TRUE; 2543 mat->assembled = PETSC_FALSE; 2544 } 2545 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2546 PetscInt irbs, rbs; 2547 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2548 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2549 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2550 } 2551 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2552 PetscInt icbs, cbs; 2553 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2554 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2555 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2556 } 2557 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2558 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2559 else { 2560 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2561 const PetscInt *irowm, *icolm; 2562 2563 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2564 bufr = buf; 2565 bufc = buf + nrow; 2566 irowm = bufr; 2567 icolm = bufc; 2568 } else { 2569 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2570 irowm = bufr; 2571 icolm = bufc; 2572 } 2573 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2574 else irowm = irow; 2575 if (mat->cmap->mapping) { 2576 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2577 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2578 } else icolm = irowm; 2579 } else icolm = icol; 2580 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2581 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2582 } 2583 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2584 PetscFunctionReturn(PETSC_SUCCESS); 2585 } 2586 2587 /*@ 2588 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2589 2590 Collective 2591 2592 Input Parameters: 2593 + mat - the matrix 2594 - x - the vector to be multiplied 2595 2596 Output Parameter: 2597 . y - the result 2598 2599 Level: developer 2600 2601 Note: 2602 The vectors `x` and `y` cannot be the same. I.e., one cannot 2603 call `MatMultDiagonalBlock`(A,y,y). 2604 2605 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2606 @*/ 2607 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2608 { 2609 PetscFunctionBegin; 2610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2611 PetscValidType(mat, 1); 2612 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2613 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2614 2615 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2616 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2617 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2618 MatCheckPreallocated(mat, 1); 2619 2620 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2621 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2622 PetscFunctionReturn(PETSC_SUCCESS); 2623 } 2624 2625 /*@ 2626 MatMult - Computes the matrix-vector product, $y = Ax$. 2627 2628 Neighbor-wise Collective 2629 2630 Input Parameters: 2631 + mat - the matrix 2632 - x - the vector to be multiplied 2633 2634 Output Parameter: 2635 . y - the result 2636 2637 Level: beginner 2638 2639 Note: 2640 The vectors `x` and `y` cannot be the same. I.e., one cannot 2641 call `MatMult`(A,y,y). 2642 2643 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2644 @*/ 2645 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2646 { 2647 PetscFunctionBegin; 2648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2649 PetscValidType(mat, 1); 2650 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2651 VecCheckAssembled(x); 2652 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2653 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2654 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2655 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2656 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); 2657 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); 2658 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); 2659 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); 2660 PetscCall(VecSetErrorIfLocked(y, 3)); 2661 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2662 MatCheckPreallocated(mat, 1); 2663 2664 PetscCall(VecLockReadPush(x)); 2665 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2666 PetscUseTypeMethod(mat, mult, x, y); 2667 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2668 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2669 PetscCall(VecLockReadPop(x)); 2670 PetscFunctionReturn(PETSC_SUCCESS); 2671 } 2672 2673 /*@ 2674 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2675 2676 Neighbor-wise Collective 2677 2678 Input Parameters: 2679 + mat - the matrix 2680 - x - the vector to be multiplied 2681 2682 Output Parameter: 2683 . y - the result 2684 2685 Level: beginner 2686 2687 Notes: 2688 The vectors `x` and `y` cannot be the same. I.e., one cannot 2689 call `MatMultTranspose`(A,y,y). 2690 2691 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2692 use `MatMultHermitianTranspose()` 2693 2694 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2695 @*/ 2696 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2697 { 2698 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2699 2700 PetscFunctionBegin; 2701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2702 PetscValidType(mat, 1); 2703 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2704 VecCheckAssembled(x); 2705 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2706 2707 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2708 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2709 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2710 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); 2711 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); 2712 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); 2713 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); 2714 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2715 MatCheckPreallocated(mat, 1); 2716 2717 if (!mat->ops->multtranspose) { 2718 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2719 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); 2720 } else op = mat->ops->multtranspose; 2721 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2722 PetscCall(VecLockReadPush(x)); 2723 PetscCall((*op)(mat, x, y)); 2724 PetscCall(VecLockReadPop(x)); 2725 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2726 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2727 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2728 PetscFunctionReturn(PETSC_SUCCESS); 2729 } 2730 2731 /*@ 2732 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2733 2734 Neighbor-wise Collective 2735 2736 Input Parameters: 2737 + mat - the matrix 2738 - x - the vector to be multiplied 2739 2740 Output Parameter: 2741 . y - the result 2742 2743 Level: beginner 2744 2745 Notes: 2746 The vectors `x` and `y` cannot be the same. I.e., one cannot 2747 call `MatMultHermitianTranspose`(A,y,y). 2748 2749 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2750 2751 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2752 2753 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2754 @*/ 2755 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2756 { 2757 PetscFunctionBegin; 2758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2759 PetscValidType(mat, 1); 2760 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2761 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2762 2763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2765 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2766 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); 2767 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); 2768 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); 2769 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); 2770 MatCheckPreallocated(mat, 1); 2771 2772 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2773 #if defined(PETSC_USE_COMPLEX) 2774 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2775 PetscCall(VecLockReadPush(x)); 2776 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2777 else PetscUseTypeMethod(mat, mult, x, y); 2778 PetscCall(VecLockReadPop(x)); 2779 } else { 2780 Vec w; 2781 PetscCall(VecDuplicate(x, &w)); 2782 PetscCall(VecCopy(x, w)); 2783 PetscCall(VecConjugate(w)); 2784 PetscCall(MatMultTranspose(mat, w, y)); 2785 PetscCall(VecDestroy(&w)); 2786 PetscCall(VecConjugate(y)); 2787 } 2788 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2789 #else 2790 PetscCall(MatMultTranspose(mat, x, y)); 2791 #endif 2792 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2793 PetscFunctionReturn(PETSC_SUCCESS); 2794 } 2795 2796 /*@ 2797 MatMultAdd - Computes $v3 = v2 + A * v1$. 2798 2799 Neighbor-wise Collective 2800 2801 Input Parameters: 2802 + mat - the matrix 2803 . v1 - the vector to be multiplied by `mat` 2804 - v2 - the vector to be added to the result 2805 2806 Output Parameter: 2807 . v3 - the result 2808 2809 Level: beginner 2810 2811 Note: 2812 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2813 call `MatMultAdd`(A,v1,v2,v1). 2814 2815 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2816 @*/ 2817 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2818 { 2819 PetscFunctionBegin; 2820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2821 PetscValidType(mat, 1); 2822 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2823 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2824 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2825 2826 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2827 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2828 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); 2829 /* 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); 2830 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); */ 2831 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); 2832 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); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 MatCheckPreallocated(mat, 1); 2835 2836 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2837 PetscCall(VecLockReadPush(v1)); 2838 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2839 PetscCall(VecLockReadPop(v1)); 2840 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2841 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2842 PetscFunctionReturn(PETSC_SUCCESS); 2843 } 2844 2845 /*@ 2846 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2847 2848 Neighbor-wise Collective 2849 2850 Input Parameters: 2851 + mat - the matrix 2852 . v1 - the vector to be multiplied by the transpose of the matrix 2853 - v2 - the vector to be added to the result 2854 2855 Output Parameter: 2856 . v3 - the result 2857 2858 Level: beginner 2859 2860 Note: 2861 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2862 call `MatMultTransposeAdd`(A,v1,v2,v1). 2863 2864 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2865 @*/ 2866 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2867 { 2868 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2869 2870 PetscFunctionBegin; 2871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2872 PetscValidType(mat, 1); 2873 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2874 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2875 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2876 2877 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2878 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2879 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); 2880 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); 2881 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); 2882 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2883 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2884 MatCheckPreallocated(mat, 1); 2885 2886 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2887 PetscCall(VecLockReadPush(v1)); 2888 PetscCall((*op)(mat, v1, v2, v3)); 2889 PetscCall(VecLockReadPop(v1)); 2890 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2891 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2892 PetscFunctionReturn(PETSC_SUCCESS); 2893 } 2894 2895 /*@ 2896 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2897 2898 Neighbor-wise Collective 2899 2900 Input Parameters: 2901 + mat - the matrix 2902 . v1 - the vector to be multiplied by the Hermitian transpose 2903 - v2 - the vector to be added to the result 2904 2905 Output Parameter: 2906 . v3 - the result 2907 2908 Level: beginner 2909 2910 Note: 2911 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2912 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2913 2914 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2915 @*/ 2916 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2917 { 2918 PetscFunctionBegin; 2919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2920 PetscValidType(mat, 1); 2921 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2922 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2923 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2924 2925 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2926 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2927 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2928 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); 2929 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); 2930 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); 2931 MatCheckPreallocated(mat, 1); 2932 2933 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2934 PetscCall(VecLockReadPush(v1)); 2935 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2936 else { 2937 Vec w, z; 2938 PetscCall(VecDuplicate(v1, &w)); 2939 PetscCall(VecCopy(v1, w)); 2940 PetscCall(VecConjugate(w)); 2941 PetscCall(VecDuplicate(v3, &z)); 2942 PetscCall(MatMultTranspose(mat, w, z)); 2943 PetscCall(VecDestroy(&w)); 2944 PetscCall(VecConjugate(z)); 2945 if (v2 != v3) { 2946 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2947 } else { 2948 PetscCall(VecAXPY(v3, 1.0, z)); 2949 } 2950 PetscCall(VecDestroy(&z)); 2951 } 2952 PetscCall(VecLockReadPop(v1)); 2953 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2954 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2955 PetscFunctionReturn(PETSC_SUCCESS); 2956 } 2957 2958 /*@ 2959 MatGetFactorType - gets the type of factorization a matrix is 2960 2961 Not Collective 2962 2963 Input Parameter: 2964 . mat - the matrix 2965 2966 Output Parameter: 2967 . 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` 2968 2969 Level: intermediate 2970 2971 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2972 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2973 @*/ 2974 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2975 { 2976 PetscFunctionBegin; 2977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2978 PetscValidType(mat, 1); 2979 PetscAssertPointer(t, 2); 2980 *t = mat->factortype; 2981 PetscFunctionReturn(PETSC_SUCCESS); 2982 } 2983 2984 /*@ 2985 MatSetFactorType - sets the type of factorization a matrix is 2986 2987 Logically Collective 2988 2989 Input Parameters: 2990 + mat - the matrix 2991 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2992 2993 Level: intermediate 2994 2995 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2996 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2997 @*/ 2998 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2999 { 3000 PetscFunctionBegin; 3001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3002 PetscValidType(mat, 1); 3003 mat->factortype = t; 3004 PetscFunctionReturn(PETSC_SUCCESS); 3005 } 3006 3007 /*@ 3008 MatGetInfo - Returns information about matrix storage (number of 3009 nonzeros, memory, etc.). 3010 3011 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3012 3013 Input Parameters: 3014 + mat - the matrix 3015 - 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) 3016 3017 Output Parameter: 3018 . info - matrix information context 3019 3020 Options Database Key: 3021 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3022 3023 Level: intermediate 3024 3025 Notes: 3026 The `MatInfo` context contains a variety of matrix data, including 3027 number of nonzeros allocated and used, number of mallocs during 3028 matrix assembly, etc. Additional information for factored matrices 3029 is provided (such as the fill ratio, number of mallocs during 3030 factorization, etc.). 3031 3032 Example: 3033 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3034 data within the `MatInfo` context. For example, 3035 .vb 3036 MatInfo info; 3037 Mat A; 3038 double mal, nz_a, nz_u; 3039 3040 MatGetInfo(A, MAT_LOCAL, &info); 3041 mal = info.mallocs; 3042 nz_a = info.nz_allocated; 3043 .ve 3044 3045 Fortran Note: 3046 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3047 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3048 a complete list of parameter names. 3049 .vb 3050 MatInfo info(MAT_INFO_SIZE) 3051 double precision mal, nz_a 3052 Mat A 3053 integer ierr 3054 3055 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3056 mal = info(MAT_INFO_MALLOCS) 3057 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3058 .ve 3059 3060 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3061 @*/ 3062 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3063 { 3064 PetscFunctionBegin; 3065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3066 PetscValidType(mat, 1); 3067 PetscAssertPointer(info, 3); 3068 MatCheckPreallocated(mat, 1); 3069 PetscUseTypeMethod(mat, getinfo, flag, info); 3070 PetscFunctionReturn(PETSC_SUCCESS); 3071 } 3072 3073 /* 3074 This is used by external packages where it is not easy to get the info from the actual 3075 matrix factorization. 3076 */ 3077 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3078 { 3079 PetscFunctionBegin; 3080 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3081 PetscFunctionReturn(PETSC_SUCCESS); 3082 } 3083 3084 /*@ 3085 MatLUFactor - Performs in-place LU factorization of matrix. 3086 3087 Collective 3088 3089 Input Parameters: 3090 + mat - the matrix 3091 . row - row permutation 3092 . col - column permutation 3093 - info - options for factorization, includes 3094 .vb 3095 fill - expected fill as ratio of original fill. 3096 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3097 Run with the option -info to determine an optimal value to use 3098 .ve 3099 3100 Level: developer 3101 3102 Notes: 3103 Most users should employ the `KSP` interface for linear solvers 3104 instead of working directly with matrix algebra routines such as this. 3105 See, e.g., `KSPCreate()`. 3106 3107 This changes the state of the matrix to a factored matrix; it cannot be used 3108 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3109 3110 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3111 when not using `KSP`. 3112 3113 Developer Note: 3114 The Fortran interface is not autogenerated as the 3115 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3116 3117 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3118 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3119 @*/ 3120 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3121 { 3122 MatFactorInfo tinfo; 3123 3124 PetscFunctionBegin; 3125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3126 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3127 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3128 if (info) PetscAssertPointer(info, 4); 3129 PetscValidType(mat, 1); 3130 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3131 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3132 MatCheckPreallocated(mat, 1); 3133 if (!info) { 3134 PetscCall(MatFactorInfoInitialize(&tinfo)); 3135 info = &tinfo; 3136 } 3137 3138 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3139 PetscUseTypeMethod(mat, lufactor, row, col, info); 3140 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3141 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3142 PetscFunctionReturn(PETSC_SUCCESS); 3143 } 3144 3145 /*@ 3146 MatILUFactor - Performs in-place ILU factorization of matrix. 3147 3148 Collective 3149 3150 Input Parameters: 3151 + mat - the matrix 3152 . row - row permutation 3153 . col - column permutation 3154 - info - structure containing 3155 .vb 3156 levels - number of levels of fill. 3157 expected fill - as ratio of original fill. 3158 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3159 missing diagonal entries) 3160 .ve 3161 3162 Level: developer 3163 3164 Notes: 3165 Most users should employ the `KSP` interface for linear solvers 3166 instead of working directly with matrix algebra routines such as this. 3167 See, e.g., `KSPCreate()`. 3168 3169 Probably really in-place only when level of fill is zero, otherwise allocates 3170 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3171 when not using `KSP`. 3172 3173 Developer Note: 3174 The Fortran interface is not autogenerated as the 3175 interface definition cannot be generated correctly [due to MatFactorInfo] 3176 3177 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3178 @*/ 3179 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3180 { 3181 PetscFunctionBegin; 3182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3183 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3184 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3185 PetscAssertPointer(info, 4); 3186 PetscValidType(mat, 1); 3187 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3188 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3189 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3190 MatCheckPreallocated(mat, 1); 3191 3192 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3193 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3194 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3195 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3196 PetscFunctionReturn(PETSC_SUCCESS); 3197 } 3198 3199 /*@ 3200 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3201 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3202 3203 Collective 3204 3205 Input Parameters: 3206 + fact - the factor matrix obtained with `MatGetFactor()` 3207 . mat - the matrix 3208 . row - the row permutation 3209 . col - the column permutation 3210 - info - options for factorization, includes 3211 .vb 3212 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3213 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3214 .ve 3215 3216 Level: developer 3217 3218 Notes: 3219 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3220 3221 Most users should employ the simplified `KSP` interface for linear solvers 3222 instead of working directly with matrix algebra routines such as this. 3223 See, e.g., `KSPCreate()`. 3224 3225 Developer Note: 3226 The Fortran interface is not autogenerated as the 3227 interface definition cannot be generated correctly [due to `MatFactorInfo`] 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 Developer Note: 3280 The Fortran interface is not autogenerated as the 3281 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3282 3283 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3284 @*/ 3285 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3286 { 3287 MatFactorInfo tinfo; 3288 3289 PetscFunctionBegin; 3290 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3292 PetscValidType(fact, 1); 3293 PetscValidType(mat, 2); 3294 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3295 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, 3296 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3297 3298 MatCheckPreallocated(mat, 2); 3299 if (!info) { 3300 PetscCall(MatFactorInfoInitialize(&tinfo)); 3301 info = &tinfo; 3302 } 3303 3304 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3305 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3306 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3307 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3308 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3309 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3310 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3311 PetscFunctionReturn(PETSC_SUCCESS); 3312 } 3313 3314 /*@ 3315 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3316 symmetric matrix. 3317 3318 Collective 3319 3320 Input Parameters: 3321 + mat - the matrix 3322 . perm - row and column permutations 3323 - info - expected fill as ratio of original fill 3324 3325 Level: developer 3326 3327 Notes: 3328 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3329 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3330 3331 Most users should employ the `KSP` interface for linear solvers 3332 instead of working directly with matrix algebra routines such as this. 3333 See, e.g., `KSPCreate()`. 3334 3335 Developer Note: 3336 The Fortran interface is not autogenerated as the 3337 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3338 3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3340 `MatGetOrdering()` 3341 @*/ 3342 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3343 { 3344 MatFactorInfo tinfo; 3345 3346 PetscFunctionBegin; 3347 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3348 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3349 if (info) PetscAssertPointer(info, 3); 3350 PetscValidType(mat, 1); 3351 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3352 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3353 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3354 MatCheckPreallocated(mat, 1); 3355 if (!info) { 3356 PetscCall(MatFactorInfoInitialize(&tinfo)); 3357 info = &tinfo; 3358 } 3359 3360 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3361 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3362 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3363 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3364 PetscFunctionReturn(PETSC_SUCCESS); 3365 } 3366 3367 /*@ 3368 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3369 of a symmetric matrix. 3370 3371 Collective 3372 3373 Input Parameters: 3374 + fact - the factor matrix obtained with `MatGetFactor()` 3375 . mat - the matrix 3376 . perm - row and column permutations 3377 - info - options for factorization, includes 3378 .vb 3379 fill - expected fill as ratio of original fill. 3380 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3381 Run with the option -info to determine an optimal value to use 3382 .ve 3383 3384 Level: developer 3385 3386 Notes: 3387 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3388 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3389 3390 Most users should employ the `KSP` interface for linear solvers 3391 instead of working directly with matrix algebra routines such as this. 3392 See, e.g., `KSPCreate()`. 3393 3394 Developer Note: 3395 The Fortran interface is not autogenerated as the 3396 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3397 3398 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3399 `MatGetOrdering()` 3400 @*/ 3401 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3402 { 3403 MatFactorInfo tinfo; 3404 3405 PetscFunctionBegin; 3406 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3407 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3408 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3409 if (info) PetscAssertPointer(info, 4); 3410 PetscValidType(fact, 1); 3411 PetscValidType(mat, 2); 3412 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3413 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3414 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3415 MatCheckPreallocated(mat, 2); 3416 if (!info) { 3417 PetscCall(MatFactorInfoInitialize(&tinfo)); 3418 info = &tinfo; 3419 } 3420 3421 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3422 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3423 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3424 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3425 PetscFunctionReturn(PETSC_SUCCESS); 3426 } 3427 3428 /*@ 3429 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3430 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3431 `MatCholeskyFactorSymbolic()`. 3432 3433 Collective 3434 3435 Input Parameters: 3436 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3437 . mat - the initial matrix that is to be factored 3438 - info - options for factorization 3439 3440 Level: developer 3441 3442 Note: 3443 Most users should employ the `KSP` interface for linear solvers 3444 instead of working directly with matrix algebra routines such as this. 3445 See, e.g., `KSPCreate()`. 3446 3447 Developer Note: 3448 The Fortran interface is not autogenerated as the 3449 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3450 3451 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3452 @*/ 3453 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3454 { 3455 MatFactorInfo tinfo; 3456 3457 PetscFunctionBegin; 3458 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3460 PetscValidType(fact, 1); 3461 PetscValidType(mat, 2); 3462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3463 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, 3464 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3465 MatCheckPreallocated(mat, 2); 3466 if (!info) { 3467 PetscCall(MatFactorInfoInitialize(&tinfo)); 3468 info = &tinfo; 3469 } 3470 3471 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3472 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3473 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3474 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3475 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3476 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3477 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3478 PetscFunctionReturn(PETSC_SUCCESS); 3479 } 3480 3481 /*@ 3482 MatQRFactor - Performs in-place QR factorization of matrix. 3483 3484 Collective 3485 3486 Input Parameters: 3487 + mat - the matrix 3488 . col - column permutation 3489 - info - options for factorization, includes 3490 .vb 3491 fill - expected fill as ratio of original fill. 3492 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3493 Run with the option -info to determine an optimal value to use 3494 .ve 3495 3496 Level: developer 3497 3498 Notes: 3499 Most users should employ the `KSP` interface for linear solvers 3500 instead of working directly with matrix algebra routines such as this. 3501 See, e.g., `KSPCreate()`. 3502 3503 This changes the state of the matrix to a factored matrix; it cannot be used 3504 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3505 3506 Developer Note: 3507 The Fortran interface is not autogenerated as the 3508 interface definition cannot be generated correctly [due to MatFactorInfo] 3509 3510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3511 `MatSetUnfactored()` 3512 @*/ 3513 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3514 { 3515 PetscFunctionBegin; 3516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3517 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3518 if (info) PetscAssertPointer(info, 3); 3519 PetscValidType(mat, 1); 3520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3522 MatCheckPreallocated(mat, 1); 3523 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3524 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3525 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3526 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3527 PetscFunctionReturn(PETSC_SUCCESS); 3528 } 3529 3530 /*@ 3531 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3532 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3533 3534 Collective 3535 3536 Input Parameters: 3537 + fact - the factor matrix obtained with `MatGetFactor()` 3538 . mat - the matrix 3539 . col - column permutation 3540 - info - options for factorization, includes 3541 .vb 3542 fill - expected fill as ratio of original fill. 3543 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3544 Run with the option -info to determine an optimal value to use 3545 .ve 3546 3547 Level: developer 3548 3549 Note: 3550 Most users should employ the `KSP` interface for linear solvers 3551 instead of working directly with matrix algebra routines such as this. 3552 See, e.g., `KSPCreate()`. 3553 3554 Developer Note: 3555 The Fortran interface is not autogenerated as the 3556 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3557 3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3559 @*/ 3560 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3561 { 3562 MatFactorInfo tinfo; 3563 3564 PetscFunctionBegin; 3565 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3567 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3568 if (info) PetscAssertPointer(info, 4); 3569 PetscValidType(fact, 1); 3570 PetscValidType(mat, 2); 3571 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3572 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3573 MatCheckPreallocated(mat, 2); 3574 if (!info) { 3575 PetscCall(MatFactorInfoInitialize(&tinfo)); 3576 info = &tinfo; 3577 } 3578 3579 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3580 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3581 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3582 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3583 PetscFunctionReturn(PETSC_SUCCESS); 3584 } 3585 3586 /*@ 3587 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3588 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3589 3590 Collective 3591 3592 Input Parameters: 3593 + fact - the factor matrix obtained with `MatGetFactor()` 3594 . mat - the matrix 3595 - info - options for factorization 3596 3597 Level: developer 3598 3599 Notes: 3600 See `MatQRFactor()` for in-place factorization. 3601 3602 Most users should employ the `KSP` interface for linear solvers 3603 instead of working directly with matrix algebra routines such as this. 3604 See, e.g., `KSPCreate()`. 3605 3606 Developer Note: 3607 The Fortran interface is not autogenerated as the 3608 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3609 3610 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3611 @*/ 3612 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3613 { 3614 MatFactorInfo tinfo; 3615 3616 PetscFunctionBegin; 3617 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3619 PetscValidType(fact, 1); 3620 PetscValidType(mat, 2); 3621 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3622 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, 3623 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3624 3625 MatCheckPreallocated(mat, 2); 3626 if (!info) { 3627 PetscCall(MatFactorInfoInitialize(&tinfo)); 3628 info = &tinfo; 3629 } 3630 3631 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3632 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3633 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3634 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3635 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3636 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3637 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 3641 /*@ 3642 MatSolve - Solves $A x = b$, given a factored matrix. 3643 3644 Neighbor-wise Collective 3645 3646 Input Parameters: 3647 + mat - the factored matrix 3648 - b - the right-hand-side vector 3649 3650 Output Parameter: 3651 . x - the result vector 3652 3653 Level: developer 3654 3655 Notes: 3656 The vectors `b` and `x` cannot be the same. I.e., one cannot 3657 call `MatSolve`(A,x,x). 3658 3659 Most users should employ the `KSP` interface for linear solvers 3660 instead of working directly with matrix algebra routines such as this. 3661 See, e.g., `KSPCreate()`. 3662 3663 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3664 @*/ 3665 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3666 { 3667 PetscFunctionBegin; 3668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3669 PetscValidType(mat, 1); 3670 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3671 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3672 PetscCheckSameComm(mat, 1, b, 2); 3673 PetscCheckSameComm(mat, 1, x, 3); 3674 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3675 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); 3676 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); 3677 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); 3678 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3679 MatCheckPreallocated(mat, 1); 3680 3681 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3682 PetscCall(VecFlag(x, mat->factorerrortype)); 3683 if (mat->factorerrortype) { 3684 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3685 } else PetscUseTypeMethod(mat, solve, b, x); 3686 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3687 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3688 PetscFunctionReturn(PETSC_SUCCESS); 3689 } 3690 3691 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3692 { 3693 Vec b, x; 3694 PetscInt N, i; 3695 PetscErrorCode (*f)(Mat, Vec, Vec); 3696 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3697 3698 PetscFunctionBegin; 3699 if (A->factorerrortype) { 3700 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3701 PetscCall(MatSetInf(X)); 3702 PetscFunctionReturn(PETSC_SUCCESS); 3703 } 3704 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3705 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3706 PetscCall(MatBoundToCPU(A, &Abound)); 3707 if (!Abound) { 3708 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3709 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3710 } 3711 #if PetscDefined(HAVE_CUDA) 3712 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3713 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3714 #elif PetscDefined(HAVE_HIP) 3715 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3716 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3717 #endif 3718 PetscCall(MatGetSize(B, NULL, &N)); 3719 for (i = 0; i < N; i++) { 3720 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3721 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3722 PetscCall((*f)(A, b, x)); 3723 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3724 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3725 } 3726 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3727 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3728 PetscFunctionReturn(PETSC_SUCCESS); 3729 } 3730 3731 /*@ 3732 MatMatSolve - Solves $A X = B$, given a factored matrix. 3733 3734 Neighbor-wise Collective 3735 3736 Input Parameters: 3737 + A - the factored matrix 3738 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3739 3740 Output Parameter: 3741 . X - the result matrix (dense matrix) 3742 3743 Level: developer 3744 3745 Note: 3746 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3747 otherwise, `B` and `X` cannot be the same. 3748 3749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3750 @*/ 3751 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3752 { 3753 PetscFunctionBegin; 3754 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3755 PetscValidType(A, 1); 3756 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3757 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3758 PetscCheckSameComm(A, 1, B, 2); 3759 PetscCheckSameComm(A, 1, X, 3); 3760 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); 3761 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); 3762 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"); 3763 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3764 MatCheckPreallocated(A, 1); 3765 3766 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3767 if (!A->ops->matsolve) { 3768 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3769 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3770 } else PetscUseTypeMethod(A, matsolve, B, X); 3771 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3772 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3773 PetscFunctionReturn(PETSC_SUCCESS); 3774 } 3775 3776 /*@ 3777 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3778 3779 Neighbor-wise Collective 3780 3781 Input Parameters: 3782 + A - the factored matrix 3783 - B - the right-hand-side matrix (`MATDENSE` matrix) 3784 3785 Output Parameter: 3786 . X - the result matrix (dense matrix) 3787 3788 Level: developer 3789 3790 Note: 3791 The matrices `B` and `X` cannot be the same. I.e., one cannot 3792 call `MatMatSolveTranspose`(A,X,X). 3793 3794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3795 @*/ 3796 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3797 { 3798 PetscFunctionBegin; 3799 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3800 PetscValidType(A, 1); 3801 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3802 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3803 PetscCheckSameComm(A, 1, B, 2); 3804 PetscCheckSameComm(A, 1, X, 3); 3805 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3806 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); 3807 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); 3808 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); 3809 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"); 3810 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3811 MatCheckPreallocated(A, 1); 3812 3813 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3814 if (!A->ops->matsolvetranspose) { 3815 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3816 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3817 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3818 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3819 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3820 PetscFunctionReturn(PETSC_SUCCESS); 3821 } 3822 3823 /*@ 3824 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3825 3826 Neighbor-wise Collective 3827 3828 Input Parameters: 3829 + A - the factored matrix 3830 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3831 3832 Output Parameter: 3833 . X - the result matrix (dense matrix) 3834 3835 Level: developer 3836 3837 Note: 3838 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 3839 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3840 3841 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3842 @*/ 3843 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3844 { 3845 PetscFunctionBegin; 3846 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3847 PetscValidType(A, 1); 3848 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3849 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3850 PetscCheckSameComm(A, 1, Bt, 2); 3851 PetscCheckSameComm(A, 1, X, 3); 3852 3853 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3854 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); 3855 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); 3856 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"); 3857 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3858 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3859 MatCheckPreallocated(A, 1); 3860 3861 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3862 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3863 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3864 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3865 PetscFunctionReturn(PETSC_SUCCESS); 3866 } 3867 3868 /*@ 3869 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3870 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3871 3872 Neighbor-wise Collective 3873 3874 Input Parameters: 3875 + mat - the factored matrix 3876 - b - the right-hand-side vector 3877 3878 Output Parameter: 3879 . x - the result vector 3880 3881 Level: developer 3882 3883 Notes: 3884 `MatSolve()` should be used for most applications, as it performs 3885 a forward solve followed by a backward solve. 3886 3887 The vectors `b` and `x` cannot be the same, i.e., one cannot 3888 call `MatForwardSolve`(A,x,x). 3889 3890 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3891 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3892 `MatForwardSolve()` solves $U^T*D y = b$, and 3893 `MatBackwardSolve()` solves $U x = y$. 3894 Thus they do not provide a symmetric preconditioner. 3895 3896 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3897 @*/ 3898 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3899 { 3900 PetscFunctionBegin; 3901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3902 PetscValidType(mat, 1); 3903 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3904 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3905 PetscCheckSameComm(mat, 1, b, 2); 3906 PetscCheckSameComm(mat, 1, x, 3); 3907 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3908 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); 3909 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); 3910 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); 3911 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3912 MatCheckPreallocated(mat, 1); 3913 3914 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3915 PetscUseTypeMethod(mat, forwardsolve, b, x); 3916 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3917 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3918 PetscFunctionReturn(PETSC_SUCCESS); 3919 } 3920 3921 /*@ 3922 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3923 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3924 3925 Neighbor-wise Collective 3926 3927 Input Parameters: 3928 + mat - the factored matrix 3929 - b - the right-hand-side vector 3930 3931 Output Parameter: 3932 . x - the result vector 3933 3934 Level: developer 3935 3936 Notes: 3937 `MatSolve()` should be used for most applications, as it performs 3938 a forward solve followed by a backward solve. 3939 3940 The vectors `b` and `x` cannot be the same. I.e., one cannot 3941 call `MatBackwardSolve`(A,x,x). 3942 3943 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3944 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3945 `MatForwardSolve()` solves $U^T*D y = b$, and 3946 `MatBackwardSolve()` solves $U x = y$. 3947 Thus they do not provide a symmetric preconditioner. 3948 3949 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3950 @*/ 3951 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3952 { 3953 PetscFunctionBegin; 3954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3955 PetscValidType(mat, 1); 3956 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3957 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3958 PetscCheckSameComm(mat, 1, b, 2); 3959 PetscCheckSameComm(mat, 1, x, 3); 3960 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3961 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); 3962 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); 3963 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); 3964 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3965 MatCheckPreallocated(mat, 1); 3966 3967 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3968 PetscUseTypeMethod(mat, backwardsolve, b, x); 3969 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3970 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3971 PetscFunctionReturn(PETSC_SUCCESS); 3972 } 3973 3974 /*@ 3975 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3976 3977 Neighbor-wise Collective 3978 3979 Input Parameters: 3980 + mat - the factored matrix 3981 . b - the right-hand-side vector 3982 - y - the vector to be added to 3983 3984 Output Parameter: 3985 . x - the result vector 3986 3987 Level: developer 3988 3989 Note: 3990 The vectors `b` and `x` cannot be the same. I.e., one cannot 3991 call `MatSolveAdd`(A,x,y,x). 3992 3993 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3994 @*/ 3995 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3996 { 3997 PetscScalar one = 1.0; 3998 Vec tmp; 3999 4000 PetscFunctionBegin; 4001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4002 PetscValidType(mat, 1); 4003 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4004 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4005 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4006 PetscCheckSameComm(mat, 1, b, 2); 4007 PetscCheckSameComm(mat, 1, y, 3); 4008 PetscCheckSameComm(mat, 1, x, 4); 4009 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4010 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); 4011 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); 4012 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); 4013 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); 4014 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); 4015 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4016 MatCheckPreallocated(mat, 1); 4017 4018 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4019 PetscCall(VecFlag(x, mat->factorerrortype)); 4020 if (mat->factorerrortype) { 4021 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4022 } else if (mat->ops->solveadd) { 4023 PetscUseTypeMethod(mat, solveadd, b, y, x); 4024 } else { 4025 /* do the solve then the add manually */ 4026 if (x != y) { 4027 PetscCall(MatSolve(mat, b, x)); 4028 PetscCall(VecAXPY(x, one, y)); 4029 } else { 4030 PetscCall(VecDuplicate(x, &tmp)); 4031 PetscCall(VecCopy(x, tmp)); 4032 PetscCall(MatSolve(mat, b, x)); 4033 PetscCall(VecAXPY(x, one, tmp)); 4034 PetscCall(VecDestroy(&tmp)); 4035 } 4036 } 4037 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4038 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4039 PetscFunctionReturn(PETSC_SUCCESS); 4040 } 4041 4042 /*@ 4043 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4044 4045 Neighbor-wise Collective 4046 4047 Input Parameters: 4048 + mat - the factored matrix 4049 - b - the right-hand-side vector 4050 4051 Output Parameter: 4052 . x - the result vector 4053 4054 Level: developer 4055 4056 Notes: 4057 The vectors `b` and `x` cannot be the same. I.e., one cannot 4058 call `MatSolveTranspose`(A,x,x). 4059 4060 Most users should employ the `KSP` interface for linear solvers 4061 instead of working directly with matrix algebra routines such as this. 4062 See, e.g., `KSPCreate()`. 4063 4064 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4065 @*/ 4066 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4067 { 4068 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4069 4070 PetscFunctionBegin; 4071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4072 PetscValidType(mat, 1); 4073 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4074 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4075 PetscCheckSameComm(mat, 1, b, 2); 4076 PetscCheckSameComm(mat, 1, x, 3); 4077 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4078 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); 4079 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); 4080 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4081 MatCheckPreallocated(mat, 1); 4082 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4083 PetscCall(VecFlag(x, mat->factorerrortype)); 4084 if (mat->factorerrortype) { 4085 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4086 } else { 4087 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4088 PetscCall((*f)(mat, b, x)); 4089 } 4090 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4091 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4092 PetscFunctionReturn(PETSC_SUCCESS); 4093 } 4094 4095 /*@ 4096 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4097 factored matrix. 4098 4099 Neighbor-wise Collective 4100 4101 Input Parameters: 4102 + mat - the factored matrix 4103 . b - the right-hand-side vector 4104 - y - the vector to be added to 4105 4106 Output Parameter: 4107 . x - the result vector 4108 4109 Level: developer 4110 4111 Note: 4112 The vectors `b` and `x` cannot be the same. I.e., one cannot 4113 call `MatSolveTransposeAdd`(A,x,y,x). 4114 4115 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4116 @*/ 4117 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4118 { 4119 PetscScalar one = 1.0; 4120 Vec tmp; 4121 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4122 4123 PetscFunctionBegin; 4124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4125 PetscValidType(mat, 1); 4126 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4127 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4128 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4129 PetscCheckSameComm(mat, 1, b, 2); 4130 PetscCheckSameComm(mat, 1, y, 3); 4131 PetscCheckSameComm(mat, 1, x, 4); 4132 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4133 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); 4134 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); 4135 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); 4136 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); 4137 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4138 MatCheckPreallocated(mat, 1); 4139 4140 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4141 PetscCall(VecFlag(x, mat->factorerrortype)); 4142 if (mat->factorerrortype) { 4143 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4144 } else if (f) { 4145 PetscCall((*f)(mat, b, y, x)); 4146 } else { 4147 /* do the solve then the add manually */ 4148 if (x != y) { 4149 PetscCall(MatSolveTranspose(mat, b, x)); 4150 PetscCall(VecAXPY(x, one, y)); 4151 } else { 4152 PetscCall(VecDuplicate(x, &tmp)); 4153 PetscCall(VecCopy(x, tmp)); 4154 PetscCall(MatSolveTranspose(mat, b, x)); 4155 PetscCall(VecAXPY(x, one, tmp)); 4156 PetscCall(VecDestroy(&tmp)); 4157 } 4158 } 4159 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4160 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4161 PetscFunctionReturn(PETSC_SUCCESS); 4162 } 4163 4164 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4165 /*@ 4166 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4167 4168 Neighbor-wise Collective 4169 4170 Input Parameters: 4171 + mat - the matrix 4172 . b - the right-hand side 4173 . omega - the relaxation factor 4174 . flag - flag indicating the type of SOR (see below) 4175 . shift - diagonal shift 4176 . its - the number of iterations 4177 - lits - the number of local iterations 4178 4179 Output Parameter: 4180 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4181 4182 SOR Flags: 4183 + `SOR_FORWARD_SWEEP` - forward SOR 4184 . `SOR_BACKWARD_SWEEP` - backward SOR 4185 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4186 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4187 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4188 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4189 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4190 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4191 upper/lower triangular part of matrix to 4192 vector (with omega) 4193 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4194 4195 Level: developer 4196 4197 Notes: 4198 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4199 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4200 on each processor. 4201 4202 Application programmers will not generally use `MatSOR()` directly, 4203 but instead will employ the `KSP`/`PC` interface. 4204 4205 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4206 4207 Most users should employ the `KSP` interface for linear solvers 4208 instead of working directly with matrix algebra routines such as this. 4209 See, e.g., `KSPCreate()`. 4210 4211 Vectors `x` and `b` CANNOT be the same 4212 4213 The flags are implemented as bitwise inclusive or operations. 4214 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4215 to specify a zero initial guess for SSOR. 4216 4217 Developer Note: 4218 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4219 4220 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4221 @*/ 4222 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4223 { 4224 PetscFunctionBegin; 4225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4226 PetscValidType(mat, 1); 4227 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4228 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4229 PetscCheckSameComm(mat, 1, b, 2); 4230 PetscCheckSameComm(mat, 1, x, 8); 4231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4232 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4233 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); 4234 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); 4235 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); 4236 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4237 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4238 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4239 4240 MatCheckPreallocated(mat, 1); 4241 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4242 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4243 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4244 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4245 PetscFunctionReturn(PETSC_SUCCESS); 4246 } 4247 4248 /* 4249 Default matrix copy routine. 4250 */ 4251 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4252 { 4253 PetscInt i, rstart = 0, rend = 0, nz; 4254 const PetscInt *cwork; 4255 const PetscScalar *vwork; 4256 4257 PetscFunctionBegin; 4258 if (B->assembled) PetscCall(MatZeroEntries(B)); 4259 if (str == SAME_NONZERO_PATTERN) { 4260 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4261 for (i = rstart; i < rend; i++) { 4262 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4263 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4264 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4265 } 4266 } else { 4267 PetscCall(MatAYPX(B, 0.0, A, str)); 4268 } 4269 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4270 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4271 PetscFunctionReturn(PETSC_SUCCESS); 4272 } 4273 4274 /*@ 4275 MatCopy - Copies a matrix to another matrix. 4276 4277 Collective 4278 4279 Input Parameters: 4280 + A - the matrix 4281 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4282 4283 Output Parameter: 4284 . B - where the copy is put 4285 4286 Level: intermediate 4287 4288 Notes: 4289 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4290 4291 `MatCopy()` copies the matrix entries of a matrix to another existing 4292 matrix (after first zeroing the second matrix). A related routine is 4293 `MatConvert()`, which first creates a new matrix and then copies the data. 4294 4295 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4296 @*/ 4297 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4298 { 4299 PetscInt i; 4300 4301 PetscFunctionBegin; 4302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4303 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4304 PetscValidType(A, 1); 4305 PetscValidType(B, 2); 4306 PetscCheckSameComm(A, 1, B, 2); 4307 MatCheckPreallocated(B, 2); 4308 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4309 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4310 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, 4311 A->cmap->N, B->cmap->N); 4312 MatCheckPreallocated(A, 1); 4313 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4314 4315 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4316 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4317 else PetscCall(MatCopy_Basic(A, B, str)); 4318 4319 B->stencil.dim = A->stencil.dim; 4320 B->stencil.noc = A->stencil.noc; 4321 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4322 B->stencil.dims[i] = A->stencil.dims[i]; 4323 B->stencil.starts[i] = A->stencil.starts[i]; 4324 } 4325 4326 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4327 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4328 PetscFunctionReturn(PETSC_SUCCESS); 4329 } 4330 4331 /*@ 4332 MatConvert - Converts a matrix to another matrix, either of the same 4333 or different type. 4334 4335 Collective 4336 4337 Input Parameters: 4338 + mat - the matrix 4339 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4340 same type as the original matrix. 4341 - reuse - denotes if the destination matrix is to be created or reused. 4342 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 4343 `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). 4344 4345 Output Parameter: 4346 . M - pointer to place new matrix 4347 4348 Level: intermediate 4349 4350 Notes: 4351 `MatConvert()` first creates a new matrix and then copies the data from 4352 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4353 entries of one matrix to another already existing matrix context. 4354 4355 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4356 the MPI communicator of the generated matrix is always the same as the communicator 4357 of the input matrix. 4358 4359 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4360 @*/ 4361 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4362 { 4363 PetscBool sametype, issame, flg; 4364 PetscBool3 issymmetric, ishermitian; 4365 char convname[256], mtype[256]; 4366 Mat B; 4367 4368 PetscFunctionBegin; 4369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4370 PetscValidType(mat, 1); 4371 PetscAssertPointer(M, 4); 4372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4373 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4374 MatCheckPreallocated(mat, 1); 4375 4376 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4377 if (flg) newtype = mtype; 4378 4379 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4380 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4381 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4382 if (reuse == MAT_REUSE_MATRIX) { 4383 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4384 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4385 } 4386 4387 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4388 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4389 PetscFunctionReturn(PETSC_SUCCESS); 4390 } 4391 4392 /* Cache Mat options because some converters use MatHeaderReplace */ 4393 issymmetric = mat->symmetric; 4394 ishermitian = mat->hermitian; 4395 4396 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4397 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4398 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4399 } else { 4400 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4401 const char *prefix[3] = {"seq", "mpi", ""}; 4402 PetscInt i; 4403 /* 4404 Order of precedence: 4405 0) See if newtype is a superclass of the current matrix. 4406 1) See if a specialized converter is known to the current matrix. 4407 2) See if a specialized converter is known to the desired matrix class. 4408 3) See if a good general converter is registered for the desired class 4409 (as of 6/27/03 only MATMPIADJ falls into this category). 4410 4) See if a good general converter is known for the current matrix. 4411 5) Use a really basic converter. 4412 */ 4413 4414 /* 0) See if newtype is a superclass of the current matrix. 4415 i.e mat is mpiaij and newtype is aij */ 4416 for (i = 0; i < 2; i++) { 4417 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4418 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4419 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4420 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4421 if (flg) { 4422 if (reuse == MAT_INPLACE_MATRIX) { 4423 PetscCall(PetscInfo(mat, "Early return\n")); 4424 PetscFunctionReturn(PETSC_SUCCESS); 4425 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4426 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4427 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4428 PetscFunctionReturn(PETSC_SUCCESS); 4429 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4430 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4431 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4432 PetscFunctionReturn(PETSC_SUCCESS); 4433 } 4434 } 4435 } 4436 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4437 for (i = 0; i < 3; i++) { 4438 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4439 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4440 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4441 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4443 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4444 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4445 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4446 if (conv) goto foundconv; 4447 } 4448 4449 /* 2) See if a specialized converter is known to the desired matrix class. */ 4450 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4451 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4452 PetscCall(MatSetType(B, newtype)); 4453 for (i = 0; i < 3; i++) { 4454 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4455 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4456 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4457 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4458 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4459 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4460 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4461 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4462 if (conv) { 4463 PetscCall(MatDestroy(&B)); 4464 goto foundconv; 4465 } 4466 } 4467 4468 /* 3) See if a good general converter is registered for the desired class */ 4469 conv = B->ops->convertfrom; 4470 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4471 PetscCall(MatDestroy(&B)); 4472 if (conv) goto foundconv; 4473 4474 /* 4) See if a good general converter is known for the current matrix */ 4475 if (mat->ops->convert) conv = mat->ops->convert; 4476 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4477 if (conv) goto foundconv; 4478 4479 /* 5) Use a really basic converter. */ 4480 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4481 conv = MatConvert_Basic; 4482 4483 foundconv: 4484 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4485 PetscCall((*conv)(mat, newtype, reuse, M)); 4486 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4487 /* the block sizes must be same if the mappings are copied over */ 4488 (*M)->rmap->bs = mat->rmap->bs; 4489 (*M)->cmap->bs = mat->cmap->bs; 4490 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4491 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4492 (*M)->rmap->mapping = mat->rmap->mapping; 4493 (*M)->cmap->mapping = mat->cmap->mapping; 4494 } 4495 (*M)->stencil.dim = mat->stencil.dim; 4496 (*M)->stencil.noc = mat->stencil.noc; 4497 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4498 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4499 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4500 } 4501 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4502 } 4503 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4504 4505 /* Copy Mat options */ 4506 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4507 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4508 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4509 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4510 PetscFunctionReturn(PETSC_SUCCESS); 4511 } 4512 4513 /*@ 4514 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4515 4516 Not Collective 4517 4518 Input Parameter: 4519 . mat - the matrix, must be a factored matrix 4520 4521 Output Parameter: 4522 . type - the string name of the package (do not free this string) 4523 4524 Level: intermediate 4525 4526 Fortran Note: 4527 Pass in an empty string that is long enough and the package name will be copied into it. 4528 4529 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4530 @*/ 4531 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4532 { 4533 PetscErrorCode (*conv)(Mat, MatSolverType *); 4534 4535 PetscFunctionBegin; 4536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4537 PetscValidType(mat, 1); 4538 PetscAssertPointer(type, 2); 4539 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4540 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4541 if (conv) PetscCall((*conv)(mat, type)); 4542 else *type = MATSOLVERPETSC; 4543 PetscFunctionReturn(PETSC_SUCCESS); 4544 } 4545 4546 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4547 struct _MatSolverTypeForSpecifcType { 4548 MatType mtype; 4549 /* no entry for MAT_FACTOR_NONE */ 4550 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4551 MatSolverTypeForSpecifcType next; 4552 }; 4553 4554 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4555 struct _MatSolverTypeHolder { 4556 char *name; 4557 MatSolverTypeForSpecifcType handlers; 4558 MatSolverTypeHolder next; 4559 }; 4560 4561 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4562 4563 /*@C 4564 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4565 4566 Logically Collective, No Fortran Support 4567 4568 Input Parameters: 4569 + package - name of the package, for example petsc or superlu 4570 . mtype - the matrix type that works with this package 4571 . ftype - the type of factorization supported by the package 4572 - createfactor - routine that will create the factored matrix ready to be used 4573 4574 Level: developer 4575 4576 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4577 `MatGetFactor()` 4578 @*/ 4579 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4580 { 4581 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4582 PetscBool flg; 4583 MatSolverTypeForSpecifcType inext, iprev = NULL; 4584 4585 PetscFunctionBegin; 4586 PetscCall(MatInitializePackage()); 4587 if (!next) { 4588 PetscCall(PetscNew(&MatSolverTypeHolders)); 4589 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4590 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4591 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4592 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4593 PetscFunctionReturn(PETSC_SUCCESS); 4594 } 4595 while (next) { 4596 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4597 if (flg) { 4598 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4599 inext = next->handlers; 4600 while (inext) { 4601 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4602 if (flg) { 4603 inext->createfactor[(int)ftype - 1] = createfactor; 4604 PetscFunctionReturn(PETSC_SUCCESS); 4605 } 4606 iprev = inext; 4607 inext = inext->next; 4608 } 4609 PetscCall(PetscNew(&iprev->next)); 4610 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4611 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4612 PetscFunctionReturn(PETSC_SUCCESS); 4613 } 4614 prev = next; 4615 next = next->next; 4616 } 4617 PetscCall(PetscNew(&prev->next)); 4618 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4619 PetscCall(PetscNew(&prev->next->handlers)); 4620 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4621 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4622 PetscFunctionReturn(PETSC_SUCCESS); 4623 } 4624 4625 /*@C 4626 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4627 4628 Input Parameters: 4629 + 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 4630 . ftype - the type of factorization supported by the type 4631 - mtype - the matrix type that works with this type 4632 4633 Output Parameters: 4634 + foundtype - `PETSC_TRUE` if the type was registered 4635 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4636 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4637 4638 Calling sequence of `createfactor`: 4639 + A - the matrix providing the factor matrix 4640 . ftype - the `MatFactorType` of the factor requested 4641 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4642 4643 Level: developer 4644 4645 Note: 4646 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4647 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4648 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4649 4650 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4651 `MatInitializePackage()` 4652 @*/ 4653 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4654 { 4655 MatSolverTypeHolder next = MatSolverTypeHolders; 4656 PetscBool flg; 4657 MatSolverTypeForSpecifcType inext; 4658 4659 PetscFunctionBegin; 4660 if (foundtype) *foundtype = PETSC_FALSE; 4661 if (foundmtype) *foundmtype = PETSC_FALSE; 4662 if (createfactor) *createfactor = NULL; 4663 4664 if (type) { 4665 while (next) { 4666 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4667 if (flg) { 4668 if (foundtype) *foundtype = PETSC_TRUE; 4669 inext = next->handlers; 4670 while (inext) { 4671 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4672 if (flg) { 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 } 4680 next = next->next; 4681 } 4682 } else { 4683 while (next) { 4684 inext = next->handlers; 4685 while (inext) { 4686 PetscCall(PetscStrcmp(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 /* try with base classes inext->mtype */ 4698 next = MatSolverTypeHolders; 4699 while (next) { 4700 inext = next->handlers; 4701 while (inext) { 4702 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4703 if (flg && inext->createfactor[(int)ftype - 1]) { 4704 if (foundtype) *foundtype = PETSC_TRUE; 4705 if (foundmtype) *foundmtype = PETSC_TRUE; 4706 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4707 PetscFunctionReturn(PETSC_SUCCESS); 4708 } 4709 inext = inext->next; 4710 } 4711 next = next->next; 4712 } 4713 } 4714 PetscFunctionReturn(PETSC_SUCCESS); 4715 } 4716 4717 PetscErrorCode MatSolverTypeDestroy(void) 4718 { 4719 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4720 MatSolverTypeForSpecifcType inext, iprev; 4721 4722 PetscFunctionBegin; 4723 while (next) { 4724 PetscCall(PetscFree(next->name)); 4725 inext = next->handlers; 4726 while (inext) { 4727 PetscCall(PetscFree(inext->mtype)); 4728 iprev = inext; 4729 inext = inext->next; 4730 PetscCall(PetscFree(iprev)); 4731 } 4732 prev = next; 4733 next = next->next; 4734 PetscCall(PetscFree(prev)); 4735 } 4736 MatSolverTypeHolders = NULL; 4737 PetscFunctionReturn(PETSC_SUCCESS); 4738 } 4739 4740 /*@ 4741 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4742 4743 Logically Collective 4744 4745 Input Parameter: 4746 . mat - the matrix 4747 4748 Output Parameter: 4749 . flg - `PETSC_TRUE` if uses the ordering 4750 4751 Level: developer 4752 4753 Note: 4754 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4755 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4756 4757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4758 @*/ 4759 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4760 { 4761 PetscFunctionBegin; 4762 *flg = mat->canuseordering; 4763 PetscFunctionReturn(PETSC_SUCCESS); 4764 } 4765 4766 /*@ 4767 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4768 4769 Logically Collective 4770 4771 Input Parameters: 4772 + mat - the matrix obtained with `MatGetFactor()` 4773 - ftype - the factorization type to be used 4774 4775 Output Parameter: 4776 . otype - the preferred ordering type 4777 4778 Level: developer 4779 4780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4781 @*/ 4782 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4783 { 4784 PetscFunctionBegin; 4785 *otype = mat->preferredordering[ftype]; 4786 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4787 PetscFunctionReturn(PETSC_SUCCESS); 4788 } 4789 4790 /*@ 4791 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4792 4793 Collective 4794 4795 Input Parameters: 4796 + mat - the matrix 4797 . 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 4798 the other criteria is returned 4799 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4800 4801 Output Parameter: 4802 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4803 4804 Options Database Keys: 4805 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4806 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4807 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4808 4809 Level: intermediate 4810 4811 Notes: 4812 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4813 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4814 4815 Users usually access the factorization solvers via `KSP` 4816 4817 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4818 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 4819 4820 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4821 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4822 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4823 4824 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4825 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4826 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4827 4828 Developer Note: 4829 This should actually be called `MatCreateFactor()` since it creates a new factor object 4830 4831 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4832 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4833 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4834 @*/ 4835 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4836 { 4837 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4838 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4839 4840 PetscFunctionBegin; 4841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4842 PetscValidType(mat, 1); 4843 4844 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4845 MatCheckPreallocated(mat, 1); 4846 4847 PetscCall(MatIsShell(mat, &shell)); 4848 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4849 if (hasop) { 4850 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4851 PetscFunctionReturn(PETSC_SUCCESS); 4852 } 4853 4854 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4855 if (!foundtype) { 4856 if (type) { 4857 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], 4858 ((PetscObject)mat)->type_name, type); 4859 } else { 4860 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); 4861 } 4862 } 4863 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4864 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); 4865 4866 PetscCall((*conv)(mat, ftype, f)); 4867 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4868 PetscFunctionReturn(PETSC_SUCCESS); 4869 } 4870 4871 /*@ 4872 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4873 4874 Not Collective 4875 4876 Input Parameters: 4877 + mat - the matrix 4878 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4879 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4880 4881 Output Parameter: 4882 . flg - PETSC_TRUE if the factorization is available 4883 4884 Level: intermediate 4885 4886 Notes: 4887 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4888 such as pastix, superlu, mumps etc. 4889 4890 PETSc must have been ./configure to use the external solver, using the option --download-package 4891 4892 Developer Note: 4893 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4894 4895 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4896 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4897 @*/ 4898 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4899 { 4900 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4901 4902 PetscFunctionBegin; 4903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4904 PetscAssertPointer(flg, 4); 4905 4906 *flg = PETSC_FALSE; 4907 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4908 4909 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4910 MatCheckPreallocated(mat, 1); 4911 4912 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4913 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4914 PetscFunctionReturn(PETSC_SUCCESS); 4915 } 4916 4917 /*@ 4918 MatDuplicate - Duplicates a matrix including the non-zero structure. 4919 4920 Collective 4921 4922 Input Parameters: 4923 + mat - the matrix 4924 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4925 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4926 4927 Output Parameter: 4928 . M - pointer to place new matrix 4929 4930 Level: intermediate 4931 4932 Notes: 4933 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4934 4935 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4936 4937 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. 4938 4939 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4940 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4941 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4942 4943 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4944 @*/ 4945 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4946 { 4947 Mat B; 4948 VecType vtype; 4949 PetscInt i; 4950 PetscObject dm, container_h, container_d; 4951 void (*viewf)(void); 4952 4953 PetscFunctionBegin; 4954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4955 PetscValidType(mat, 1); 4956 PetscAssertPointer(M, 3); 4957 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4958 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4959 MatCheckPreallocated(mat, 1); 4960 4961 *M = NULL; 4962 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4963 PetscUseTypeMethod(mat, duplicate, op, M); 4964 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4965 B = *M; 4966 4967 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4968 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4969 PetscCall(MatGetVecType(mat, &vtype)); 4970 PetscCall(MatSetVecType(B, vtype)); 4971 4972 B->stencil.dim = mat->stencil.dim; 4973 B->stencil.noc = mat->stencil.noc; 4974 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4975 B->stencil.dims[i] = mat->stencil.dims[i]; 4976 B->stencil.starts[i] = mat->stencil.starts[i]; 4977 } 4978 4979 B->nooffproczerorows = mat->nooffproczerorows; 4980 B->nooffprocentries = mat->nooffprocentries; 4981 4982 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4983 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4984 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4985 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4986 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4987 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4988 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4989 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4990 PetscFunctionReturn(PETSC_SUCCESS); 4991 } 4992 4993 /*@ 4994 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4995 4996 Logically Collective 4997 4998 Input Parameter: 4999 . mat - the matrix 5000 5001 Output Parameter: 5002 . v - the diagonal of the matrix 5003 5004 Level: intermediate 5005 5006 Note: 5007 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5008 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5009 is larger than `ndiag`, the values of the remaining entries are unspecified. 5010 5011 Currently only correct in parallel for square matrices. 5012 5013 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5014 @*/ 5015 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5016 { 5017 PetscFunctionBegin; 5018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5019 PetscValidType(mat, 1); 5020 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5021 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5022 MatCheckPreallocated(mat, 1); 5023 if (PetscDefined(USE_DEBUG)) { 5024 PetscInt nv, row, col, ndiag; 5025 5026 PetscCall(VecGetLocalSize(v, &nv)); 5027 PetscCall(MatGetLocalSize(mat, &row, &col)); 5028 ndiag = PetscMin(row, col); 5029 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); 5030 } 5031 5032 PetscUseTypeMethod(mat, getdiagonal, v); 5033 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5034 PetscFunctionReturn(PETSC_SUCCESS); 5035 } 5036 5037 /*@ 5038 MatGetRowMin - Gets the minimum value (of the real part) of each 5039 row of the matrix 5040 5041 Logically Collective 5042 5043 Input Parameter: 5044 . mat - the matrix 5045 5046 Output Parameters: 5047 + v - the vector for storing the maximums 5048 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5049 5050 Level: intermediate 5051 5052 Note: 5053 The result of this call are the same as if one converted the matrix to dense format 5054 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5055 5056 This code is only implemented for a couple of matrix formats. 5057 5058 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5059 `MatGetRowMax()` 5060 @*/ 5061 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5062 { 5063 PetscFunctionBegin; 5064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5065 PetscValidType(mat, 1); 5066 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5067 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5068 5069 if (!mat->cmap->N) { 5070 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5071 if (idx) { 5072 PetscInt i, m = mat->rmap->n; 5073 for (i = 0; i < m; i++) idx[i] = -1; 5074 } 5075 } else { 5076 MatCheckPreallocated(mat, 1); 5077 } 5078 PetscUseTypeMethod(mat, getrowmin, v, idx); 5079 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5080 PetscFunctionReturn(PETSC_SUCCESS); 5081 } 5082 5083 /*@ 5084 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5085 row of the matrix 5086 5087 Logically Collective 5088 5089 Input Parameter: 5090 . mat - the matrix 5091 5092 Output Parameters: 5093 + v - the vector for storing the minimums 5094 - idx - the indices of the column found for each row (or `NULL` if not needed) 5095 5096 Level: intermediate 5097 5098 Notes: 5099 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5100 row is 0 (the first column). 5101 5102 This code is only implemented for a couple of matrix formats. 5103 5104 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5105 @*/ 5106 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5107 { 5108 PetscFunctionBegin; 5109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5110 PetscValidType(mat, 1); 5111 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5112 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5113 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5114 5115 if (!mat->cmap->N) { 5116 PetscCall(VecSet(v, 0.0)); 5117 if (idx) { 5118 PetscInt i, m = mat->rmap->n; 5119 for (i = 0; i < m; i++) idx[i] = -1; 5120 } 5121 } else { 5122 MatCheckPreallocated(mat, 1); 5123 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5124 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5125 } 5126 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5127 PetscFunctionReturn(PETSC_SUCCESS); 5128 } 5129 5130 /*@ 5131 MatGetRowMax - Gets the maximum value (of the real part) of each 5132 row of the matrix 5133 5134 Logically Collective 5135 5136 Input Parameter: 5137 . mat - the matrix 5138 5139 Output Parameters: 5140 + v - the vector for storing the maximums 5141 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5142 5143 Level: intermediate 5144 5145 Notes: 5146 The result of this call are the same as if one converted the matrix to dense format 5147 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5148 5149 This code is only implemented for a couple of matrix formats. 5150 5151 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5152 @*/ 5153 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5154 { 5155 PetscFunctionBegin; 5156 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5157 PetscValidType(mat, 1); 5158 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5159 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5160 5161 if (!mat->cmap->N) { 5162 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5163 if (idx) { 5164 PetscInt i, m = mat->rmap->n; 5165 for (i = 0; i < m; i++) idx[i] = -1; 5166 } 5167 } else { 5168 MatCheckPreallocated(mat, 1); 5169 PetscUseTypeMethod(mat, getrowmax, v, idx); 5170 } 5171 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5172 PetscFunctionReturn(PETSC_SUCCESS); 5173 } 5174 5175 /*@ 5176 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5177 row of the matrix 5178 5179 Logically Collective 5180 5181 Input Parameter: 5182 . mat - the matrix 5183 5184 Output Parameters: 5185 + v - the vector for storing the maximums 5186 - idx - the indices of the column found for each row (or `NULL` if not needed) 5187 5188 Level: intermediate 5189 5190 Notes: 5191 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5192 row is 0 (the first column). 5193 5194 This code is only implemented for a couple of matrix formats. 5195 5196 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5197 @*/ 5198 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5199 { 5200 PetscFunctionBegin; 5201 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5202 PetscValidType(mat, 1); 5203 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5205 5206 if (!mat->cmap->N) { 5207 PetscCall(VecSet(v, 0.0)); 5208 if (idx) { 5209 PetscInt i, m = mat->rmap->n; 5210 for (i = 0; i < m; i++) idx[i] = -1; 5211 } 5212 } else { 5213 MatCheckPreallocated(mat, 1); 5214 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5215 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5216 } 5217 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5218 PetscFunctionReturn(PETSC_SUCCESS); 5219 } 5220 5221 /*@ 5222 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5223 5224 Logically Collective 5225 5226 Input Parameter: 5227 . mat - the matrix 5228 5229 Output Parameter: 5230 . v - the vector for storing the sum 5231 5232 Level: intermediate 5233 5234 This code is only implemented for a couple of matrix formats. 5235 5236 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5237 @*/ 5238 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5239 { 5240 PetscFunctionBegin; 5241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5242 PetscValidType(mat, 1); 5243 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5244 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5245 5246 if (!mat->cmap->N) { 5247 PetscCall(VecSet(v, 0.0)); 5248 } else { 5249 MatCheckPreallocated(mat, 1); 5250 PetscUseTypeMethod(mat, getrowsumabs, v); 5251 } 5252 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5253 PetscFunctionReturn(PETSC_SUCCESS); 5254 } 5255 5256 /*@ 5257 MatGetRowSum - Gets the sum of each row of the matrix 5258 5259 Logically or Neighborhood Collective 5260 5261 Input Parameter: 5262 . mat - the matrix 5263 5264 Output Parameter: 5265 . v - the vector for storing the sum of rows 5266 5267 Level: intermediate 5268 5269 Note: 5270 This code is slow since it is not currently specialized for different formats 5271 5272 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5273 @*/ 5274 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5275 { 5276 Vec ones; 5277 5278 PetscFunctionBegin; 5279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5280 PetscValidType(mat, 1); 5281 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5282 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5283 MatCheckPreallocated(mat, 1); 5284 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5285 PetscCall(VecSet(ones, 1.)); 5286 PetscCall(MatMult(mat, ones, v)); 5287 PetscCall(VecDestroy(&ones)); 5288 PetscFunctionReturn(PETSC_SUCCESS); 5289 } 5290 5291 /*@ 5292 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5293 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5294 5295 Collective 5296 5297 Input Parameter: 5298 . mat - the matrix to provide the transpose 5299 5300 Output Parameter: 5301 . 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 5302 5303 Level: advanced 5304 5305 Note: 5306 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 5307 routine allows bypassing that call. 5308 5309 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5310 @*/ 5311 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5312 { 5313 PetscContainer rB = NULL; 5314 MatParentState *rb = NULL; 5315 5316 PetscFunctionBegin; 5317 PetscCall(PetscNew(&rb)); 5318 rb->id = ((PetscObject)mat)->id; 5319 rb->state = 0; 5320 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5321 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5322 PetscCall(PetscContainerSetPointer(rB, rb)); 5323 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5324 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5325 PetscCall(PetscObjectDereference((PetscObject)rB)); 5326 PetscFunctionReturn(PETSC_SUCCESS); 5327 } 5328 5329 /*@ 5330 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5331 5332 Collective 5333 5334 Input Parameters: 5335 + mat - the matrix to transpose 5336 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5337 5338 Output Parameter: 5339 . B - the transpose 5340 5341 Level: intermediate 5342 5343 Notes: 5344 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5345 5346 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the 5347 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5348 5349 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. 5350 5351 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5352 5353 If mat is unchanged from the last call this function returns immediately without recomputing the result 5354 5355 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5356 5357 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5358 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5359 @*/ 5360 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5361 { 5362 PetscContainer rB = NULL; 5363 MatParentState *rb = NULL; 5364 5365 PetscFunctionBegin; 5366 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5367 PetscValidType(mat, 1); 5368 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5369 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5370 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5371 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5372 MatCheckPreallocated(mat, 1); 5373 if (reuse == MAT_REUSE_MATRIX) { 5374 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5375 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5376 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5377 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5378 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5379 } 5380 5381 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5382 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5383 PetscUseTypeMethod(mat, transpose, reuse, B); 5384 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5385 } 5386 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5387 5388 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5389 if (reuse != MAT_INPLACE_MATRIX) { 5390 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5391 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5392 rb->state = ((PetscObject)mat)->state; 5393 rb->nonzerostate = mat->nonzerostate; 5394 } 5395 PetscFunctionReturn(PETSC_SUCCESS); 5396 } 5397 5398 /*@ 5399 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5400 5401 Collective 5402 5403 Input Parameter: 5404 . A - the matrix to transpose 5405 5406 Output Parameter: 5407 . 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 5408 numerical portion. 5409 5410 Level: intermediate 5411 5412 Note: 5413 This is not supported for many matrix types, use `MatTranspose()` in those cases 5414 5415 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5416 @*/ 5417 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5418 { 5419 PetscFunctionBegin; 5420 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5421 PetscValidType(A, 1); 5422 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5423 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5424 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5425 PetscUseTypeMethod(A, transposesymbolic, B); 5426 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5427 5428 PetscCall(MatTransposeSetPrecursor(A, *B)); 5429 PetscFunctionReturn(PETSC_SUCCESS); 5430 } 5431 5432 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5433 { 5434 PetscContainer rB; 5435 MatParentState *rb; 5436 5437 PetscFunctionBegin; 5438 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5439 PetscValidType(A, 1); 5440 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5441 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5442 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5443 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5444 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5445 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5446 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5447 PetscFunctionReturn(PETSC_SUCCESS); 5448 } 5449 5450 /*@ 5451 MatIsTranspose - Test whether a matrix is another one's transpose, 5452 or its own, in which case it tests symmetry. 5453 5454 Collective 5455 5456 Input Parameters: 5457 + A - the matrix to test 5458 . B - the matrix to test against, this can equal the first parameter 5459 - tol - tolerance, differences between entries smaller than this are counted as zero 5460 5461 Output Parameter: 5462 . flg - the result 5463 5464 Level: intermediate 5465 5466 Notes: 5467 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5468 test involves parallel copies of the block off-diagonal parts of the matrix. 5469 5470 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5471 @*/ 5472 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5473 { 5474 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5475 5476 PetscFunctionBegin; 5477 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5478 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5479 PetscAssertPointer(flg, 4); 5480 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5481 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5482 *flg = PETSC_FALSE; 5483 if (f && g) { 5484 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5485 PetscCall((*f)(A, B, tol, flg)); 5486 } else { 5487 MatType mattype; 5488 5489 PetscCall(MatGetType(f ? B : A, &mattype)); 5490 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5491 } 5492 PetscFunctionReturn(PETSC_SUCCESS); 5493 } 5494 5495 /*@ 5496 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5497 5498 Collective 5499 5500 Input Parameters: 5501 + mat - the matrix to transpose and complex conjugate 5502 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5503 5504 Output Parameter: 5505 . B - the Hermitian transpose 5506 5507 Level: intermediate 5508 5509 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5510 @*/ 5511 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5512 { 5513 PetscFunctionBegin; 5514 PetscCall(MatTranspose(mat, reuse, B)); 5515 #if defined(PETSC_USE_COMPLEX) 5516 PetscCall(MatConjugate(*B)); 5517 #endif 5518 PetscFunctionReturn(PETSC_SUCCESS); 5519 } 5520 5521 /*@ 5522 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5523 5524 Collective 5525 5526 Input Parameters: 5527 + A - the matrix to test 5528 . B - the matrix to test against, this can equal the first parameter 5529 - tol - tolerance, differences between entries smaller than this are counted as zero 5530 5531 Output Parameter: 5532 . flg - the result 5533 5534 Level: intermediate 5535 5536 Notes: 5537 Only available for `MATAIJ` matrices. 5538 5539 The sequential algorithm 5540 has a running time of the order of the number of nonzeros; the parallel 5541 test involves parallel copies of the block off-diagonal parts of the matrix. 5542 5543 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5544 @*/ 5545 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5546 { 5547 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5548 5549 PetscFunctionBegin; 5550 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5551 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5552 PetscAssertPointer(flg, 4); 5553 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5554 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5555 if (f && g) { 5556 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5557 PetscCall((*f)(A, B, tol, flg)); 5558 } 5559 PetscFunctionReturn(PETSC_SUCCESS); 5560 } 5561 5562 /*@ 5563 MatPermute - Creates a new matrix with rows and columns permuted from the 5564 original. 5565 5566 Collective 5567 5568 Input Parameters: 5569 + mat - the matrix to permute 5570 . row - row permutation, each processor supplies only the permutation for its rows 5571 - col - column permutation, each processor supplies only the permutation for its columns 5572 5573 Output Parameter: 5574 . B - the permuted matrix 5575 5576 Level: advanced 5577 5578 Note: 5579 The index sets map from row/col of permuted matrix to row/col of original matrix. 5580 The index sets should be on the same communicator as mat and have the same local sizes. 5581 5582 Developer Note: 5583 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5584 exploit the fact that row and col are permutations, consider implementing the 5585 more general `MatCreateSubMatrix()` instead. 5586 5587 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5588 @*/ 5589 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5590 { 5591 PetscFunctionBegin; 5592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5593 PetscValidType(mat, 1); 5594 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5595 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5596 PetscAssertPointer(B, 4); 5597 PetscCheckSameComm(mat, 1, row, 2); 5598 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5599 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5600 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5601 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5602 MatCheckPreallocated(mat, 1); 5603 5604 if (mat->ops->permute) { 5605 PetscUseTypeMethod(mat, permute, row, col, B); 5606 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5607 } else { 5608 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5609 } 5610 PetscFunctionReturn(PETSC_SUCCESS); 5611 } 5612 5613 /*@ 5614 MatEqual - Compares two matrices. 5615 5616 Collective 5617 5618 Input Parameters: 5619 + A - the first matrix 5620 - B - the second matrix 5621 5622 Output Parameter: 5623 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5624 5625 Level: intermediate 5626 5627 .seealso: [](ch_matrices), `Mat` 5628 @*/ 5629 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5630 { 5631 PetscFunctionBegin; 5632 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5633 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5634 PetscValidType(A, 1); 5635 PetscValidType(B, 2); 5636 PetscAssertPointer(flg, 3); 5637 PetscCheckSameComm(A, 1, B, 2); 5638 MatCheckPreallocated(A, 1); 5639 MatCheckPreallocated(B, 2); 5640 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5641 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5642 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, 5643 B->cmap->N); 5644 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5645 PetscUseTypeMethod(A, equal, B, flg); 5646 } else { 5647 PetscCall(MatMultEqual(A, B, 10, flg)); 5648 } 5649 PetscFunctionReturn(PETSC_SUCCESS); 5650 } 5651 5652 /*@ 5653 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5654 matrices that are stored as vectors. Either of the two scaling 5655 matrices can be `NULL`. 5656 5657 Collective 5658 5659 Input Parameters: 5660 + mat - the matrix to be scaled 5661 . l - the left scaling vector (or `NULL`) 5662 - r - the right scaling vector (or `NULL`) 5663 5664 Level: intermediate 5665 5666 Note: 5667 `MatDiagonalScale()` computes $A = LAR$, where 5668 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5669 The L scales the rows of the matrix, the R scales the columns of the matrix. 5670 5671 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5672 @*/ 5673 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5674 { 5675 PetscFunctionBegin; 5676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5677 PetscValidType(mat, 1); 5678 if (l) { 5679 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5680 PetscCheckSameComm(mat, 1, l, 2); 5681 } 5682 if (r) { 5683 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5684 PetscCheckSameComm(mat, 1, r, 3); 5685 } 5686 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5687 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5688 MatCheckPreallocated(mat, 1); 5689 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5690 5691 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5692 PetscUseTypeMethod(mat, diagonalscale, l, r); 5693 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5694 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5695 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5696 PetscFunctionReturn(PETSC_SUCCESS); 5697 } 5698 5699 /*@ 5700 MatScale - Scales all elements of a matrix by a given number. 5701 5702 Logically Collective 5703 5704 Input Parameters: 5705 + mat - the matrix to be scaled 5706 - a - the scaling value 5707 5708 Level: intermediate 5709 5710 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5711 @*/ 5712 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5713 { 5714 PetscFunctionBegin; 5715 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5716 PetscValidType(mat, 1); 5717 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5718 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5719 PetscValidLogicalCollectiveScalar(mat, a, 2); 5720 MatCheckPreallocated(mat, 1); 5721 5722 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5723 if (a != (PetscScalar)1.0) { 5724 PetscUseTypeMethod(mat, scale, a); 5725 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5726 } 5727 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5728 PetscFunctionReturn(PETSC_SUCCESS); 5729 } 5730 5731 /*@ 5732 MatNorm - Calculates various norms of a matrix. 5733 5734 Collective 5735 5736 Input Parameters: 5737 + mat - the matrix 5738 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5739 5740 Output Parameter: 5741 . nrm - the resulting norm 5742 5743 Level: intermediate 5744 5745 .seealso: [](ch_matrices), `Mat` 5746 @*/ 5747 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5748 { 5749 PetscFunctionBegin; 5750 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5751 PetscValidType(mat, 1); 5752 PetscAssertPointer(nrm, 3); 5753 5754 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5755 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5756 MatCheckPreallocated(mat, 1); 5757 5758 PetscUseTypeMethod(mat, norm, type, nrm); 5759 PetscFunctionReturn(PETSC_SUCCESS); 5760 } 5761 5762 /* 5763 This variable is used to prevent counting of MatAssemblyBegin() that 5764 are called from within a MatAssemblyEnd(). 5765 */ 5766 static PetscInt MatAssemblyEnd_InUse = 0; 5767 /*@ 5768 MatAssemblyBegin - Begins assembling the matrix. This routine should 5769 be called after completing all calls to `MatSetValues()`. 5770 5771 Collective 5772 5773 Input Parameters: 5774 + mat - the matrix 5775 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5776 5777 Level: beginner 5778 5779 Notes: 5780 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5781 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5782 5783 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5784 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5785 using the matrix. 5786 5787 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5788 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 5789 a global collective operation requiring all processes that share the matrix. 5790 5791 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5792 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5793 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5794 5795 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5796 @*/ 5797 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5798 { 5799 PetscFunctionBegin; 5800 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5801 PetscValidType(mat, 1); 5802 MatCheckPreallocated(mat, 1); 5803 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5804 if (mat->assembled) { 5805 mat->was_assembled = PETSC_TRUE; 5806 mat->assembled = PETSC_FALSE; 5807 } 5808 5809 if (!MatAssemblyEnd_InUse) { 5810 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5811 PetscTryTypeMethod(mat, assemblybegin, type); 5812 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5813 } else PetscTryTypeMethod(mat, assemblybegin, type); 5814 PetscFunctionReturn(PETSC_SUCCESS); 5815 } 5816 5817 /*@ 5818 MatAssembled - Indicates if a matrix has been assembled and is ready for 5819 use; for example, in matrix-vector product. 5820 5821 Not Collective 5822 5823 Input Parameter: 5824 . mat - the matrix 5825 5826 Output Parameter: 5827 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5828 5829 Level: advanced 5830 5831 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5832 @*/ 5833 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5834 { 5835 PetscFunctionBegin; 5836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5837 PetscAssertPointer(assembled, 2); 5838 *assembled = mat->assembled; 5839 PetscFunctionReturn(PETSC_SUCCESS); 5840 } 5841 5842 /*@ 5843 MatAssemblyEnd - Completes assembling the matrix. This routine should 5844 be called after `MatAssemblyBegin()`. 5845 5846 Collective 5847 5848 Input Parameters: 5849 + mat - the matrix 5850 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5851 5852 Options Database Keys: 5853 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5854 . -mat_view ::ascii_info_detail - Prints more detailed info 5855 . -mat_view - Prints matrix in ASCII format 5856 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5857 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5858 . -display <name> - Sets display name (default is host) 5859 . -draw_pause <sec> - Sets number of seconds to pause after display 5860 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5861 . -viewer_socket_machine <machine> - Machine to use for socket 5862 . -viewer_socket_port <port> - Port number to use for socket 5863 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5864 5865 Level: beginner 5866 5867 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5868 @*/ 5869 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5870 { 5871 static PetscInt inassm = 0; 5872 PetscBool flg = PETSC_FALSE; 5873 5874 PetscFunctionBegin; 5875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5876 PetscValidType(mat, 1); 5877 5878 inassm++; 5879 MatAssemblyEnd_InUse++; 5880 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5881 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5882 PetscTryTypeMethod(mat, assemblyend, type); 5883 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5884 } else PetscTryTypeMethod(mat, assemblyend, type); 5885 5886 /* Flush assembly is not a true assembly */ 5887 if (type != MAT_FLUSH_ASSEMBLY) { 5888 if (mat->num_ass) { 5889 if (!mat->symmetry_eternal) { 5890 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5891 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5892 } 5893 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5894 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5895 } 5896 mat->num_ass++; 5897 mat->assembled = PETSC_TRUE; 5898 mat->ass_nonzerostate = mat->nonzerostate; 5899 } 5900 5901 mat->insertmode = NOT_SET_VALUES; 5902 MatAssemblyEnd_InUse--; 5903 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5904 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5905 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5906 5907 if (mat->checksymmetryonassembly) { 5908 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5909 if (flg) { 5910 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5911 } else { 5912 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5913 } 5914 } 5915 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5916 } 5917 inassm--; 5918 PetscFunctionReturn(PETSC_SUCCESS); 5919 } 5920 5921 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5922 /*@ 5923 MatSetOption - Sets a parameter option for a matrix. Some options 5924 may be specific to certain storage formats. Some options 5925 determine how values will be inserted (or added). Sorted, 5926 row-oriented input will generally assemble the fastest. The default 5927 is row-oriented. 5928 5929 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5930 5931 Input Parameters: 5932 + mat - the matrix 5933 . op - the option, one of those listed below (and possibly others), 5934 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5935 5936 Options Describing Matrix Structure: 5937 + `MAT_SPD` - symmetric positive definite 5938 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5939 . `MAT_HERMITIAN` - transpose is the complex conjugation 5940 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5941 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5942 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5943 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5944 5945 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5946 do not need to be computed (usually at a high cost) 5947 5948 Options For Use with `MatSetValues()`: 5949 Insert a logically dense subblock, which can be 5950 . `MAT_ROW_ORIENTED` - row-oriented (default) 5951 5952 These options reflect the data you pass in with `MatSetValues()`; it has 5953 nothing to do with how the data is stored internally in the matrix 5954 data structure. 5955 5956 When (re)assembling a matrix, we can restrict the input for 5957 efficiency/debugging purposes. These options include 5958 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5959 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5960 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5961 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5962 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5963 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5964 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5965 performance for very large process counts. 5966 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5967 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5968 functions, instead sending only neighbor messages. 5969 5970 Level: intermediate 5971 5972 Notes: 5973 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5974 5975 Some options are relevant only for particular matrix types and 5976 are thus ignored by others. Other options are not supported by 5977 certain matrix types and will generate an error message if set. 5978 5979 If using Fortran to compute a matrix, one may need to 5980 use the column-oriented option (or convert to the row-oriented 5981 format). 5982 5983 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5984 that would generate a new entry in the nonzero structure is instead 5985 ignored. Thus, if memory has not already been allocated for this particular 5986 data, then the insertion is ignored. For dense matrices, in which 5987 the entire array is allocated, no entries are ever ignored. 5988 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5989 5990 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5991 that would generate a new entry in the nonzero structure instead produces 5992 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 5993 5994 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5995 that would generate a new entry that has not been preallocated will 5996 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5997 only.) This is a useful flag when debugging matrix memory preallocation. 5998 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5999 6000 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6001 other processors should be dropped, rather than stashed. 6002 This is useful if you know that the "owning" processor is also 6003 always generating the correct matrix entries, so that PETSc need 6004 not transfer duplicate entries generated on another processor. 6005 6006 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6007 searches during matrix assembly. When this flag is set, the hash table 6008 is created during the first matrix assembly. This hash table is 6009 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6010 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6011 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6012 supported by `MATMPIBAIJ` format only. 6013 6014 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6015 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6016 6017 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6018 a zero location in the matrix 6019 6020 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6021 6022 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6023 zero row routines and thus improves performance for very large process counts. 6024 6025 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6026 part of the matrix (since they should match the upper triangular part). 6027 6028 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6029 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6030 with finite difference schemes with non-periodic boundary conditions. 6031 6032 Developer Note: 6033 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6034 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6035 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6036 not changed. 6037 6038 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6039 @*/ 6040 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6041 { 6042 PetscFunctionBegin; 6043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6044 if (op > 0) { 6045 PetscValidLogicalCollectiveEnum(mat, op, 2); 6046 PetscValidLogicalCollectiveBool(mat, flg, 3); 6047 } 6048 6049 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); 6050 6051 switch (op) { 6052 case MAT_FORCE_DIAGONAL_ENTRIES: 6053 mat->force_diagonals = flg; 6054 PetscFunctionReturn(PETSC_SUCCESS); 6055 case MAT_NO_OFF_PROC_ENTRIES: 6056 mat->nooffprocentries = flg; 6057 PetscFunctionReturn(PETSC_SUCCESS); 6058 case MAT_SUBSET_OFF_PROC_ENTRIES: 6059 mat->assembly_subset = flg; 6060 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6061 #if !defined(PETSC_HAVE_MPIUNI) 6062 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6063 #endif 6064 mat->stash.first_assembly_done = PETSC_FALSE; 6065 } 6066 PetscFunctionReturn(PETSC_SUCCESS); 6067 case MAT_NO_OFF_PROC_ZERO_ROWS: 6068 mat->nooffproczerorows = flg; 6069 PetscFunctionReturn(PETSC_SUCCESS); 6070 case MAT_SPD: 6071 if (flg) { 6072 mat->spd = PETSC_BOOL3_TRUE; 6073 mat->symmetric = PETSC_BOOL3_TRUE; 6074 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6075 } else { 6076 mat->spd = PETSC_BOOL3_FALSE; 6077 } 6078 break; 6079 case MAT_SYMMETRIC: 6080 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6081 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6082 #if !defined(PETSC_USE_COMPLEX) 6083 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6084 #endif 6085 break; 6086 case MAT_HERMITIAN: 6087 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6088 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6089 #if !defined(PETSC_USE_COMPLEX) 6090 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6091 #endif 6092 break; 6093 case MAT_STRUCTURALLY_SYMMETRIC: 6094 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6095 break; 6096 case MAT_SYMMETRY_ETERNAL: 6097 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"); 6098 mat->symmetry_eternal = flg; 6099 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6100 break; 6101 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6102 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"); 6103 mat->structural_symmetry_eternal = flg; 6104 break; 6105 case MAT_SPD_ETERNAL: 6106 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"); 6107 mat->spd_eternal = flg; 6108 if (flg) { 6109 mat->structural_symmetry_eternal = PETSC_TRUE; 6110 mat->symmetry_eternal = PETSC_TRUE; 6111 } 6112 break; 6113 case MAT_STRUCTURE_ONLY: 6114 mat->structure_only = flg; 6115 break; 6116 case MAT_SORTED_FULL: 6117 mat->sortedfull = flg; 6118 break; 6119 default: 6120 break; 6121 } 6122 PetscTryTypeMethod(mat, setoption, op, flg); 6123 PetscFunctionReturn(PETSC_SUCCESS); 6124 } 6125 6126 /*@ 6127 MatGetOption - Gets a parameter option that has been set for a matrix. 6128 6129 Logically Collective 6130 6131 Input Parameters: 6132 + mat - the matrix 6133 - op - the option, this only responds to certain options, check the code for which ones 6134 6135 Output Parameter: 6136 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6137 6138 Level: intermediate 6139 6140 Notes: 6141 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6142 6143 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6144 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6145 6146 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6147 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6148 @*/ 6149 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6150 { 6151 PetscFunctionBegin; 6152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6153 PetscValidType(mat, 1); 6154 6155 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); 6156 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()"); 6157 6158 switch (op) { 6159 case MAT_NO_OFF_PROC_ENTRIES: 6160 *flg = mat->nooffprocentries; 6161 break; 6162 case MAT_NO_OFF_PROC_ZERO_ROWS: 6163 *flg = mat->nooffproczerorows; 6164 break; 6165 case MAT_SYMMETRIC: 6166 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6167 break; 6168 case MAT_HERMITIAN: 6169 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6170 break; 6171 case MAT_STRUCTURALLY_SYMMETRIC: 6172 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6173 break; 6174 case MAT_SPD: 6175 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6176 break; 6177 case MAT_SYMMETRY_ETERNAL: 6178 *flg = mat->symmetry_eternal; 6179 break; 6180 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6181 *flg = mat->symmetry_eternal; 6182 break; 6183 default: 6184 break; 6185 } 6186 PetscFunctionReturn(PETSC_SUCCESS); 6187 } 6188 6189 /*@ 6190 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6191 this routine retains the old nonzero structure. 6192 6193 Logically Collective 6194 6195 Input Parameter: 6196 . mat - the matrix 6197 6198 Level: intermediate 6199 6200 Note: 6201 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. 6202 See the Performance chapter of the users manual for information on preallocating matrices. 6203 6204 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6205 @*/ 6206 PetscErrorCode MatZeroEntries(Mat mat) 6207 { 6208 PetscFunctionBegin; 6209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6210 PetscValidType(mat, 1); 6211 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6212 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"); 6213 MatCheckPreallocated(mat, 1); 6214 6215 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6216 PetscUseTypeMethod(mat, zeroentries); 6217 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6218 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6219 PetscFunctionReturn(PETSC_SUCCESS); 6220 } 6221 6222 /*@ 6223 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6224 of a set of rows and columns of a matrix. 6225 6226 Collective 6227 6228 Input Parameters: 6229 + mat - the matrix 6230 . numRows - the number of rows/columns to zero 6231 . rows - the global row indices 6232 . diag - value put in the diagonal of the eliminated rows 6233 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6234 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6235 6236 Level: intermediate 6237 6238 Notes: 6239 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6240 6241 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6242 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 6243 6244 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6245 Krylov method to take advantage of the known solution on the zeroed rows. 6246 6247 For the parallel case, all processes that share the matrix (i.e., 6248 those in the communicator used for matrix creation) MUST call this 6249 routine, regardless of whether any rows being zeroed are owned by 6250 them. 6251 6252 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6253 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 6254 missing. 6255 6256 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6257 list only rows local to itself). 6258 6259 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6260 6261 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6262 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6263 @*/ 6264 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6265 { 6266 PetscFunctionBegin; 6267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6268 PetscValidType(mat, 1); 6269 if (numRows) PetscAssertPointer(rows, 3); 6270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6272 MatCheckPreallocated(mat, 1); 6273 6274 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6275 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6276 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6277 PetscFunctionReturn(PETSC_SUCCESS); 6278 } 6279 6280 /*@ 6281 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6282 of a set of rows and columns of a matrix. 6283 6284 Collective 6285 6286 Input Parameters: 6287 + mat - the matrix 6288 . is - the rows to zero 6289 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6290 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6291 - b - optional vector of right-hand side, that will be adjusted by provided solution 6292 6293 Level: intermediate 6294 6295 Note: 6296 See `MatZeroRowsColumns()` for details on how this routine operates. 6297 6298 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6299 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6300 @*/ 6301 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6302 { 6303 PetscInt numRows; 6304 const PetscInt *rows; 6305 6306 PetscFunctionBegin; 6307 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6308 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6309 PetscValidType(mat, 1); 6310 PetscValidType(is, 2); 6311 PetscCall(ISGetLocalSize(is, &numRows)); 6312 PetscCall(ISGetIndices(is, &rows)); 6313 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6314 PetscCall(ISRestoreIndices(is, &rows)); 6315 PetscFunctionReturn(PETSC_SUCCESS); 6316 } 6317 6318 /*@ 6319 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6320 of a set of rows of a matrix. 6321 6322 Collective 6323 6324 Input Parameters: 6325 + mat - the matrix 6326 . numRows - the number of rows to zero 6327 . rows - the global row indices 6328 . diag - value put in the diagonal of the zeroed rows 6329 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6330 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6331 6332 Level: intermediate 6333 6334 Notes: 6335 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6336 6337 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6338 6339 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6340 Krylov method to take advantage of the known solution on the zeroed rows. 6341 6342 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) 6343 from the matrix. 6344 6345 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6346 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal 6347 formats this does not alter the nonzero structure. 6348 6349 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6350 of the matrix is not changed the values are 6351 merely zeroed. 6352 6353 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6354 formats can optionally remove the main diagonal entry from the 6355 nonzero structure as well, by passing 0.0 as the final argument). 6356 6357 For the parallel case, all processes that share the matrix (i.e., 6358 those in the communicator used for matrix creation) MUST call this 6359 routine, regardless of whether any rows being zeroed are owned by 6360 them. 6361 6362 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6363 list only rows local to itself). 6364 6365 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6366 owns that are to be zeroed. This saves a global synchronization in the implementation. 6367 6368 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6369 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6370 @*/ 6371 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6372 { 6373 PetscFunctionBegin; 6374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6375 PetscValidType(mat, 1); 6376 if (numRows) PetscAssertPointer(rows, 3); 6377 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6378 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6379 MatCheckPreallocated(mat, 1); 6380 6381 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6382 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6383 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6384 PetscFunctionReturn(PETSC_SUCCESS); 6385 } 6386 6387 /*@ 6388 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6389 of a set of rows of a matrix. 6390 6391 Collective 6392 6393 Input Parameters: 6394 + mat - the matrix 6395 . is - index set of rows to remove (if `NULL` then no row is removed) 6396 . diag - value put in all diagonals of eliminated rows 6397 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6398 - b - optional vector of right-hand side, that will be adjusted by provided solution 6399 6400 Level: intermediate 6401 6402 Note: 6403 See `MatZeroRows()` for details on how this routine operates. 6404 6405 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6406 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6407 @*/ 6408 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6409 { 6410 PetscInt numRows = 0; 6411 const PetscInt *rows = NULL; 6412 6413 PetscFunctionBegin; 6414 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6415 PetscValidType(mat, 1); 6416 if (is) { 6417 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6418 PetscCall(ISGetLocalSize(is, &numRows)); 6419 PetscCall(ISGetIndices(is, &rows)); 6420 } 6421 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6422 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6423 PetscFunctionReturn(PETSC_SUCCESS); 6424 } 6425 6426 /*@ 6427 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6428 of a set of rows of a matrix. These rows must be local to the process. 6429 6430 Collective 6431 6432 Input Parameters: 6433 + mat - the matrix 6434 . numRows - the number of rows to remove 6435 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6436 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6437 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6438 - b - optional vector of right-hand side, that will be adjusted by provided solution 6439 6440 Level: intermediate 6441 6442 Notes: 6443 See `MatZeroRows()` for details on how this routine operates. 6444 6445 The grid coordinates are across the entire grid, not just the local portion 6446 6447 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6448 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6449 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6450 `DM_BOUNDARY_PERIODIC` boundary type. 6451 6452 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 6453 a single value per point) you can skip filling those indices. 6454 6455 Fortran Note: 6456 `idxm` and `idxn` should be declared as 6457 $ MatStencil idxm(4, m) 6458 and the values inserted using 6459 .vb 6460 idxm(MatStencil_i, 1) = i 6461 idxm(MatStencil_j, 1) = j 6462 idxm(MatStencil_k, 1) = k 6463 idxm(MatStencil_c, 1) = c 6464 etc 6465 .ve 6466 6467 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6468 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6469 @*/ 6470 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6471 { 6472 PetscInt dim = mat->stencil.dim; 6473 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6474 PetscInt *dims = mat->stencil.dims + 1; 6475 PetscInt *starts = mat->stencil.starts; 6476 PetscInt *dxm = (PetscInt *)rows; 6477 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6478 6479 PetscFunctionBegin; 6480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6481 PetscValidType(mat, 1); 6482 if (numRows) PetscAssertPointer(rows, 3); 6483 6484 PetscCall(PetscMalloc1(numRows, &jdxm)); 6485 for (i = 0; i < numRows; ++i) { 6486 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6487 for (j = 0; j < 3 - sdim; ++j) dxm++; 6488 /* Local index in X dir */ 6489 tmp = *dxm++ - starts[0]; 6490 /* Loop over remaining dimensions */ 6491 for (j = 0; j < dim - 1; ++j) { 6492 /* If nonlocal, set index to be negative */ 6493 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6494 /* Update local index */ 6495 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6496 } 6497 /* Skip component slot if necessary */ 6498 if (mat->stencil.noc) dxm++; 6499 /* Local row number */ 6500 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6501 } 6502 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6503 PetscCall(PetscFree(jdxm)); 6504 PetscFunctionReturn(PETSC_SUCCESS); 6505 } 6506 6507 /*@ 6508 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6509 of a set of rows and columns of a matrix. 6510 6511 Collective 6512 6513 Input Parameters: 6514 + mat - the matrix 6515 . numRows - the number of rows/columns to remove 6516 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6517 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6518 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6519 - b - optional vector of right-hand side, that will be adjusted by provided solution 6520 6521 Level: intermediate 6522 6523 Notes: 6524 See `MatZeroRowsColumns()` for details on how this routine operates. 6525 6526 The grid coordinates are across the entire grid, not just the local portion 6527 6528 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6529 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6530 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6531 `DM_BOUNDARY_PERIODIC` boundary type. 6532 6533 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 6534 a single value per point) you can skip filling those indices. 6535 6536 Fortran Note: 6537 `idxm` and `idxn` should be declared as 6538 $ MatStencil idxm(4, m) 6539 and the values inserted using 6540 .vb 6541 idxm(MatStencil_i, 1) = i 6542 idxm(MatStencil_j, 1) = j 6543 idxm(MatStencil_k, 1) = k 6544 idxm(MatStencil_c, 1) = c 6545 etc 6546 .ve 6547 6548 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6549 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6550 @*/ 6551 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6552 { 6553 PetscInt dim = mat->stencil.dim; 6554 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6555 PetscInt *dims = mat->stencil.dims + 1; 6556 PetscInt *starts = mat->stencil.starts; 6557 PetscInt *dxm = (PetscInt *)rows; 6558 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6559 6560 PetscFunctionBegin; 6561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6562 PetscValidType(mat, 1); 6563 if (numRows) PetscAssertPointer(rows, 3); 6564 6565 PetscCall(PetscMalloc1(numRows, &jdxm)); 6566 for (i = 0; i < numRows; ++i) { 6567 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6568 for (j = 0; j < 3 - sdim; ++j) dxm++; 6569 /* Local index in X dir */ 6570 tmp = *dxm++ - starts[0]; 6571 /* Loop over remaining dimensions */ 6572 for (j = 0; j < dim - 1; ++j) { 6573 /* If nonlocal, set index to be negative */ 6574 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6575 /* Update local index */ 6576 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6577 } 6578 /* Skip component slot if necessary */ 6579 if (mat->stencil.noc) dxm++; 6580 /* Local row number */ 6581 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6582 } 6583 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6584 PetscCall(PetscFree(jdxm)); 6585 PetscFunctionReturn(PETSC_SUCCESS); 6586 } 6587 6588 /*@ 6589 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6590 of a set of rows of a matrix; using local numbering of rows. 6591 6592 Collective 6593 6594 Input Parameters: 6595 + mat - the matrix 6596 . numRows - the number of rows to remove 6597 . rows - the local row indices 6598 . diag - value put in all diagonals of eliminated rows 6599 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6600 - b - optional vector of right-hand side, that will be adjusted by provided solution 6601 6602 Level: intermediate 6603 6604 Notes: 6605 Before calling `MatZeroRowsLocal()`, the user must first set the 6606 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6607 6608 See `MatZeroRows()` for details on how this routine operates. 6609 6610 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6611 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6612 @*/ 6613 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6614 { 6615 PetscFunctionBegin; 6616 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6617 PetscValidType(mat, 1); 6618 if (numRows) PetscAssertPointer(rows, 3); 6619 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6620 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6621 MatCheckPreallocated(mat, 1); 6622 6623 if (mat->ops->zerorowslocal) { 6624 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6625 } else { 6626 IS is, newis; 6627 const PetscInt *newRows; 6628 6629 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6630 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6631 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6632 PetscCall(ISGetIndices(newis, &newRows)); 6633 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6634 PetscCall(ISRestoreIndices(newis, &newRows)); 6635 PetscCall(ISDestroy(&newis)); 6636 PetscCall(ISDestroy(&is)); 6637 } 6638 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6639 PetscFunctionReturn(PETSC_SUCCESS); 6640 } 6641 6642 /*@ 6643 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6644 of a set of rows of a matrix; using local numbering of rows. 6645 6646 Collective 6647 6648 Input Parameters: 6649 + mat - the matrix 6650 . is - index set of rows to remove 6651 . diag - value put in all diagonals of eliminated rows 6652 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6653 - b - optional vector of right-hand side, that will be adjusted by provided solution 6654 6655 Level: intermediate 6656 6657 Notes: 6658 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6659 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6660 6661 See `MatZeroRows()` for details on how this routine operates. 6662 6663 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6664 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6665 @*/ 6666 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6667 { 6668 PetscInt numRows; 6669 const PetscInt *rows; 6670 6671 PetscFunctionBegin; 6672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6673 PetscValidType(mat, 1); 6674 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6675 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6676 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6677 MatCheckPreallocated(mat, 1); 6678 6679 PetscCall(ISGetLocalSize(is, &numRows)); 6680 PetscCall(ISGetIndices(is, &rows)); 6681 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6682 PetscCall(ISRestoreIndices(is, &rows)); 6683 PetscFunctionReturn(PETSC_SUCCESS); 6684 } 6685 6686 /*@ 6687 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6688 of a set of rows and columns of a matrix; using local numbering of rows. 6689 6690 Collective 6691 6692 Input Parameters: 6693 + mat - the matrix 6694 . numRows - the number of rows to remove 6695 . rows - the global row indices 6696 . diag - value put in all diagonals of eliminated rows 6697 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6698 - b - optional vector of right-hand side, that will be adjusted by provided solution 6699 6700 Level: intermediate 6701 6702 Notes: 6703 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6704 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6705 6706 See `MatZeroRowsColumns()` for details on how this routine operates. 6707 6708 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6709 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6710 @*/ 6711 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6712 { 6713 IS is, newis; 6714 const PetscInt *newRows; 6715 6716 PetscFunctionBegin; 6717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6718 PetscValidType(mat, 1); 6719 if (numRows) PetscAssertPointer(rows, 3); 6720 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6721 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6722 MatCheckPreallocated(mat, 1); 6723 6724 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6725 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6726 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6727 PetscCall(ISGetIndices(newis, &newRows)); 6728 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6729 PetscCall(ISRestoreIndices(newis, &newRows)); 6730 PetscCall(ISDestroy(&newis)); 6731 PetscCall(ISDestroy(&is)); 6732 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6733 PetscFunctionReturn(PETSC_SUCCESS); 6734 } 6735 6736 /*@ 6737 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6738 of a set of rows and columns of a matrix; using local numbering of rows. 6739 6740 Collective 6741 6742 Input Parameters: 6743 + mat - the matrix 6744 . is - index set of rows to remove 6745 . diag - value put in all diagonals of eliminated rows 6746 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6747 - b - optional vector of right-hand side, that will be adjusted by provided solution 6748 6749 Level: intermediate 6750 6751 Notes: 6752 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6753 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6754 6755 See `MatZeroRowsColumns()` for details on how this routine operates. 6756 6757 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6758 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6759 @*/ 6760 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6761 { 6762 PetscInt numRows; 6763 const PetscInt *rows; 6764 6765 PetscFunctionBegin; 6766 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6767 PetscValidType(mat, 1); 6768 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6769 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6770 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6771 MatCheckPreallocated(mat, 1); 6772 6773 PetscCall(ISGetLocalSize(is, &numRows)); 6774 PetscCall(ISGetIndices(is, &rows)); 6775 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6776 PetscCall(ISRestoreIndices(is, &rows)); 6777 PetscFunctionReturn(PETSC_SUCCESS); 6778 } 6779 6780 /*@ 6781 MatGetSize - Returns the numbers of rows and columns in a matrix. 6782 6783 Not Collective 6784 6785 Input Parameter: 6786 . mat - the matrix 6787 6788 Output Parameters: 6789 + m - the number of global rows 6790 - n - the number of global columns 6791 6792 Level: beginner 6793 6794 Note: 6795 Both output parameters can be `NULL` on input. 6796 6797 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6798 @*/ 6799 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6800 { 6801 PetscFunctionBegin; 6802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6803 if (m) *m = mat->rmap->N; 6804 if (n) *n = mat->cmap->N; 6805 PetscFunctionReturn(PETSC_SUCCESS); 6806 } 6807 6808 /*@ 6809 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6810 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6811 6812 Not Collective 6813 6814 Input Parameter: 6815 . mat - the matrix 6816 6817 Output Parameters: 6818 + m - the number of local rows, use `NULL` to not obtain this value 6819 - n - the number of local columns, use `NULL` to not obtain this value 6820 6821 Level: beginner 6822 6823 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6824 @*/ 6825 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6826 { 6827 PetscFunctionBegin; 6828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6829 if (m) PetscAssertPointer(m, 2); 6830 if (n) PetscAssertPointer(n, 3); 6831 if (m) *m = mat->rmap->n; 6832 if (n) *n = mat->cmap->n; 6833 PetscFunctionReturn(PETSC_SUCCESS); 6834 } 6835 6836 /*@ 6837 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6838 vector one multiplies this matrix by that are owned by this processor. 6839 6840 Not Collective, unless matrix has not been allocated, then collective 6841 6842 Input Parameter: 6843 . mat - the matrix 6844 6845 Output Parameters: 6846 + m - the global index of the first local column, use `NULL` to not obtain this value 6847 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6848 6849 Level: developer 6850 6851 Notes: 6852 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6853 6854 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6855 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6856 6857 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6858 the local values in the matrix. 6859 6860 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6861 Layouts](sec_matlayout) for details on matrix layouts. 6862 6863 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6864 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6865 @*/ 6866 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6867 { 6868 PetscFunctionBegin; 6869 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6870 PetscValidType(mat, 1); 6871 if (m) PetscAssertPointer(m, 2); 6872 if (n) PetscAssertPointer(n, 3); 6873 MatCheckPreallocated(mat, 1); 6874 if (m) *m = mat->cmap->rstart; 6875 if (n) *n = mat->cmap->rend; 6876 PetscFunctionReturn(PETSC_SUCCESS); 6877 } 6878 6879 /*@ 6880 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6881 this MPI process. 6882 6883 Not Collective 6884 6885 Input Parameter: 6886 . mat - the matrix 6887 6888 Output Parameters: 6889 + m - the global index of the first local row, use `NULL` to not obtain this value 6890 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6891 6892 Level: beginner 6893 6894 Notes: 6895 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6896 6897 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6898 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6899 6900 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6901 the local values in the matrix. 6902 6903 The high argument is one more than the last element stored locally. 6904 6905 For all matrices it returns the range of matrix rows associated with rows of a vector that 6906 would contain the result of a matrix vector product with this matrix. See [Matrix 6907 Layouts](sec_matlayout) for details on matrix layouts. 6908 6909 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6910 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6911 @*/ 6912 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6913 { 6914 PetscFunctionBegin; 6915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6916 PetscValidType(mat, 1); 6917 if (m) PetscAssertPointer(m, 2); 6918 if (n) PetscAssertPointer(n, 3); 6919 MatCheckPreallocated(mat, 1); 6920 if (m) *m = mat->rmap->rstart; 6921 if (n) *n = mat->rmap->rend; 6922 PetscFunctionReturn(PETSC_SUCCESS); 6923 } 6924 6925 /*@C 6926 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6927 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6928 6929 Not Collective, unless matrix has not been allocated 6930 6931 Input Parameter: 6932 . mat - the matrix 6933 6934 Output Parameter: 6935 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6936 where `size` is the number of MPI processes used by `mat` 6937 6938 Level: beginner 6939 6940 Notes: 6941 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6942 6943 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6944 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6945 6946 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6947 the local values in the matrix. 6948 6949 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6950 would contain the result of a matrix vector product with this matrix. See [Matrix 6951 Layouts](sec_matlayout) for details on matrix layouts. 6952 6953 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6954 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6955 `DMDAGetGhostCorners()`, `DM` 6956 @*/ 6957 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6958 { 6959 PetscFunctionBegin; 6960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6961 PetscValidType(mat, 1); 6962 MatCheckPreallocated(mat, 1); 6963 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6964 PetscFunctionReturn(PETSC_SUCCESS); 6965 } 6966 6967 /*@C 6968 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6969 vector one multiplies this vector by that are owned by each processor. 6970 6971 Not Collective, unless matrix has not been allocated 6972 6973 Input Parameter: 6974 . mat - the matrix 6975 6976 Output Parameter: 6977 . ranges - start of each processors portion plus one more than the total length at the end 6978 6979 Level: beginner 6980 6981 Notes: 6982 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6983 6984 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6985 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6986 6987 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6988 the local values in the matrix. 6989 6990 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6991 Layouts](sec_matlayout) for details on matrix layouts. 6992 6993 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6994 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6995 `DMDAGetGhostCorners()`, `DM` 6996 @*/ 6997 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6998 { 6999 PetscFunctionBegin; 7000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7001 PetscValidType(mat, 1); 7002 MatCheckPreallocated(mat, 1); 7003 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7004 PetscFunctionReturn(PETSC_SUCCESS); 7005 } 7006 7007 /*@ 7008 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7009 7010 Not Collective 7011 7012 Input Parameter: 7013 . A - matrix 7014 7015 Output Parameters: 7016 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7017 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7018 7019 Level: intermediate 7020 7021 Note: 7022 You should call `ISDestroy()` on the returned `IS` 7023 7024 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7025 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7026 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7027 details on matrix layouts. 7028 7029 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7030 @*/ 7031 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7032 { 7033 PetscErrorCode (*f)(Mat, IS *, IS *); 7034 7035 PetscFunctionBegin; 7036 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7037 PetscValidType(A, 1); 7038 MatCheckPreallocated(A, 1); 7039 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7040 if (f) { 7041 PetscCall((*f)(A, rows, cols)); 7042 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7043 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7044 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7045 } 7046 PetscFunctionReturn(PETSC_SUCCESS); 7047 } 7048 7049 /*@ 7050 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7051 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7052 to complete the factorization. 7053 7054 Collective 7055 7056 Input Parameters: 7057 + fact - the factorized matrix obtained with `MatGetFactor()` 7058 . mat - the matrix 7059 . row - row permutation 7060 . col - column permutation 7061 - info - structure containing 7062 .vb 7063 levels - number of levels of fill. 7064 expected fill - as ratio of original fill. 7065 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7066 missing diagonal entries) 7067 .ve 7068 7069 Level: developer 7070 7071 Notes: 7072 See [Matrix Factorization](sec_matfactor) for additional information. 7073 7074 Most users should employ the `KSP` interface for linear solvers 7075 instead of working directly with matrix algebra routines such as this. 7076 See, e.g., `KSPCreate()`. 7077 7078 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7079 7080 Developer Note: 7081 The Fortran interface is not autogenerated as the 7082 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7083 7084 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7085 `MatGetOrdering()`, `MatFactorInfo` 7086 @*/ 7087 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7088 { 7089 PetscFunctionBegin; 7090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7091 PetscValidType(mat, 2); 7092 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7093 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7094 PetscAssertPointer(info, 5); 7095 PetscAssertPointer(fact, 1); 7096 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7097 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7098 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7099 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7100 MatCheckPreallocated(mat, 2); 7101 7102 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7103 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7104 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7105 PetscFunctionReturn(PETSC_SUCCESS); 7106 } 7107 7108 /*@ 7109 MatICCFactorSymbolic - Performs symbolic incomplete 7110 Cholesky factorization for a symmetric matrix. Use 7111 `MatCholeskyFactorNumeric()` to complete the factorization. 7112 7113 Collective 7114 7115 Input Parameters: 7116 + fact - the factorized matrix obtained with `MatGetFactor()` 7117 . mat - the matrix to be factored 7118 . perm - row and column permutation 7119 - info - structure containing 7120 .vb 7121 levels - number of levels of fill. 7122 expected fill - as ratio of original fill. 7123 .ve 7124 7125 Level: developer 7126 7127 Notes: 7128 Most users should employ the `KSP` interface for linear solvers 7129 instead of working directly with matrix algebra routines such as this. 7130 See, e.g., `KSPCreate()`. 7131 7132 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7133 7134 Developer Note: 7135 The Fortran interface is not autogenerated as the 7136 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7137 7138 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7139 @*/ 7140 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7141 { 7142 PetscFunctionBegin; 7143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7144 PetscValidType(mat, 2); 7145 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7146 PetscAssertPointer(info, 4); 7147 PetscAssertPointer(fact, 1); 7148 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7149 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7150 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7151 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7152 MatCheckPreallocated(mat, 2); 7153 7154 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7155 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7156 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7157 PetscFunctionReturn(PETSC_SUCCESS); 7158 } 7159 7160 /*@C 7161 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7162 points to an array of valid matrices, they may be reused to store the new 7163 submatrices. 7164 7165 Collective 7166 7167 Input Parameters: 7168 + mat - the matrix 7169 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7170 . irow - index set of rows to extract 7171 . icol - index set of columns to extract 7172 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7173 7174 Output Parameter: 7175 . submat - the array of submatrices 7176 7177 Level: advanced 7178 7179 Notes: 7180 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7181 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7182 to extract a parallel submatrix. 7183 7184 Some matrix types place restrictions on the row and column 7185 indices, such as that they be sorted or that they be equal to each other. 7186 7187 The index sets may not have duplicate entries. 7188 7189 When extracting submatrices from a parallel matrix, each processor can 7190 form a different submatrix by setting the rows and columns of its 7191 individual index sets according to the local submatrix desired. 7192 7193 When finished using the submatrices, the user should destroy 7194 them with `MatDestroySubMatrices()`. 7195 7196 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7197 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7198 7199 This routine creates the matrices in submat; you should NOT create them before 7200 calling it. It also allocates the array of matrix pointers submat. 7201 7202 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7203 request one row/column in a block, they must request all rows/columns that are in 7204 that block. For example, if the block size is 2 you cannot request just row 0 and 7205 column 0. 7206 7207 Fortran Note: 7208 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7209 7210 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7211 @*/ 7212 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7213 { 7214 PetscInt i; 7215 PetscBool eq; 7216 7217 PetscFunctionBegin; 7218 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7219 PetscValidType(mat, 1); 7220 if (n) { 7221 PetscAssertPointer(irow, 3); 7222 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7223 PetscAssertPointer(icol, 4); 7224 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7225 } 7226 PetscAssertPointer(submat, 6); 7227 if (n && scall == MAT_REUSE_MATRIX) { 7228 PetscAssertPointer(*submat, 6); 7229 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7230 } 7231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7232 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7233 MatCheckPreallocated(mat, 1); 7234 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7235 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7236 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7237 for (i = 0; i < n; i++) { 7238 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7239 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7240 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7241 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7242 if (mat->boundtocpu && mat->bindingpropagates) { 7243 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7244 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7245 } 7246 #endif 7247 } 7248 PetscFunctionReturn(PETSC_SUCCESS); 7249 } 7250 7251 /*@C 7252 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7253 7254 Collective 7255 7256 Input Parameters: 7257 + mat - the matrix 7258 . n - the number of submatrixes to be extracted 7259 . irow - index set of rows to extract 7260 . icol - index set of columns to extract 7261 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7262 7263 Output Parameter: 7264 . submat - the array of submatrices 7265 7266 Level: advanced 7267 7268 Note: 7269 This is used by `PCGASM` 7270 7271 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7272 @*/ 7273 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7274 { 7275 PetscInt i; 7276 PetscBool eq; 7277 7278 PetscFunctionBegin; 7279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7280 PetscValidType(mat, 1); 7281 if (n) { 7282 PetscAssertPointer(irow, 3); 7283 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7284 PetscAssertPointer(icol, 4); 7285 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7286 } 7287 PetscAssertPointer(submat, 6); 7288 if (n && scall == MAT_REUSE_MATRIX) { 7289 PetscAssertPointer(*submat, 6); 7290 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7291 } 7292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7294 MatCheckPreallocated(mat, 1); 7295 7296 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7297 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7298 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7299 for (i = 0; i < n; i++) { 7300 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7301 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7302 } 7303 PetscFunctionReturn(PETSC_SUCCESS); 7304 } 7305 7306 /*@C 7307 MatDestroyMatrices - Destroys an array of matrices. 7308 7309 Collective 7310 7311 Input Parameters: 7312 + n - the number of local matrices 7313 - mat - the matrices (this is a pointer to the array of matrices) 7314 7315 Level: advanced 7316 7317 Notes: 7318 Frees not only the matrices, but also the array that contains the matrices 7319 7320 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7321 7322 Fortran Note: 7323 Does not free the `mat` array. 7324 7325 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7326 @*/ 7327 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7328 { 7329 PetscInt i; 7330 7331 PetscFunctionBegin; 7332 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7333 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7334 PetscAssertPointer(mat, 2); 7335 7336 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7337 7338 /* memory is allocated even if n = 0 */ 7339 PetscCall(PetscFree(*mat)); 7340 PetscFunctionReturn(PETSC_SUCCESS); 7341 } 7342 7343 /*@C 7344 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7345 7346 Collective 7347 7348 Input Parameters: 7349 + n - the number of local matrices 7350 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7351 sequence of `MatCreateSubMatrices()`) 7352 7353 Level: advanced 7354 7355 Note: 7356 Frees not only the matrices, but also the array that contains the matrices 7357 7358 Fortran Note: 7359 Does not free the `mat` array. 7360 7361 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7362 @*/ 7363 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7364 { 7365 Mat mat0; 7366 7367 PetscFunctionBegin; 7368 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7369 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7370 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7371 PetscAssertPointer(mat, 2); 7372 7373 mat0 = (*mat)[0]; 7374 if (mat0 && mat0->ops->destroysubmatrices) { 7375 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7376 } else { 7377 PetscCall(MatDestroyMatrices(n, mat)); 7378 } 7379 PetscFunctionReturn(PETSC_SUCCESS); 7380 } 7381 7382 /*@ 7383 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7384 7385 Collective 7386 7387 Input Parameter: 7388 . mat - the matrix 7389 7390 Output Parameter: 7391 . matstruct - the sequential matrix with the nonzero structure of `mat` 7392 7393 Level: developer 7394 7395 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7396 @*/ 7397 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7398 { 7399 PetscFunctionBegin; 7400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7401 PetscAssertPointer(matstruct, 2); 7402 7403 PetscValidType(mat, 1); 7404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7405 MatCheckPreallocated(mat, 1); 7406 7407 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7408 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7409 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7410 PetscFunctionReturn(PETSC_SUCCESS); 7411 } 7412 7413 /*@C 7414 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7415 7416 Collective 7417 7418 Input Parameter: 7419 . mat - the matrix 7420 7421 Level: advanced 7422 7423 Note: 7424 This is not needed, one can just call `MatDestroy()` 7425 7426 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7427 @*/ 7428 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7429 { 7430 PetscFunctionBegin; 7431 PetscAssertPointer(mat, 1); 7432 PetscCall(MatDestroy(mat)); 7433 PetscFunctionReturn(PETSC_SUCCESS); 7434 } 7435 7436 /*@ 7437 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7438 replaces the index sets by larger ones that represent submatrices with 7439 additional overlap. 7440 7441 Collective 7442 7443 Input Parameters: 7444 + mat - the matrix 7445 . n - the number of index sets 7446 . is - the array of index sets (these index sets will changed during the call) 7447 - ov - the additional overlap requested 7448 7449 Options Database Key: 7450 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7451 7452 Level: developer 7453 7454 Note: 7455 The computed overlap preserves the matrix block sizes when the blocks are square. 7456 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7457 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7458 7459 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7460 @*/ 7461 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7462 { 7463 PetscInt i, bs, cbs; 7464 7465 PetscFunctionBegin; 7466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7467 PetscValidType(mat, 1); 7468 PetscValidLogicalCollectiveInt(mat, n, 2); 7469 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7470 if (n) { 7471 PetscAssertPointer(is, 3); 7472 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7473 } 7474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7476 MatCheckPreallocated(mat, 1); 7477 7478 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7479 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7480 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7481 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7482 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7483 if (bs == cbs) { 7484 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7485 } 7486 PetscFunctionReturn(PETSC_SUCCESS); 7487 } 7488 7489 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7490 7491 /*@ 7492 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7493 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7494 additional overlap. 7495 7496 Collective 7497 7498 Input Parameters: 7499 + mat - the matrix 7500 . n - the number of index sets 7501 . is - the array of index sets (these index sets will changed during the call) 7502 - ov - the additional overlap requested 7503 7504 ` Options Database Key: 7505 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7506 7507 Level: developer 7508 7509 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7510 @*/ 7511 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7512 { 7513 PetscInt i; 7514 7515 PetscFunctionBegin; 7516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7517 PetscValidType(mat, 1); 7518 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7519 if (n) { 7520 PetscAssertPointer(is, 3); 7521 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7522 } 7523 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7524 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7525 MatCheckPreallocated(mat, 1); 7526 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7527 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7528 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7529 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7530 PetscFunctionReturn(PETSC_SUCCESS); 7531 } 7532 7533 /*@ 7534 MatGetBlockSize - Returns the matrix block size. 7535 7536 Not Collective 7537 7538 Input Parameter: 7539 . mat - the matrix 7540 7541 Output Parameter: 7542 . bs - block size 7543 7544 Level: intermediate 7545 7546 Notes: 7547 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7548 7549 If the block size has not been set yet this routine returns 1. 7550 7551 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7552 @*/ 7553 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7554 { 7555 PetscFunctionBegin; 7556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7557 PetscAssertPointer(bs, 2); 7558 *bs = PetscAbs(mat->rmap->bs); 7559 PetscFunctionReturn(PETSC_SUCCESS); 7560 } 7561 7562 /*@ 7563 MatGetBlockSizes - Returns the matrix block row and column sizes. 7564 7565 Not Collective 7566 7567 Input Parameter: 7568 . mat - the matrix 7569 7570 Output Parameters: 7571 + rbs - row block size 7572 - cbs - column block size 7573 7574 Level: intermediate 7575 7576 Notes: 7577 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7578 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7579 7580 If a block size has not been set yet this routine returns 1. 7581 7582 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7583 @*/ 7584 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7585 { 7586 PetscFunctionBegin; 7587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7588 if (rbs) PetscAssertPointer(rbs, 2); 7589 if (cbs) PetscAssertPointer(cbs, 3); 7590 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7591 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7592 PetscFunctionReturn(PETSC_SUCCESS); 7593 } 7594 7595 /*@ 7596 MatSetBlockSize - Sets the matrix block size. 7597 7598 Logically Collective 7599 7600 Input Parameters: 7601 + mat - the matrix 7602 - bs - block size 7603 7604 Level: intermediate 7605 7606 Notes: 7607 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7608 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7609 7610 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7611 is compatible with the matrix local sizes. 7612 7613 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7614 @*/ 7615 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7616 { 7617 PetscFunctionBegin; 7618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7619 PetscValidLogicalCollectiveInt(mat, bs, 2); 7620 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7621 PetscFunctionReturn(PETSC_SUCCESS); 7622 } 7623 7624 typedef struct { 7625 PetscInt n; 7626 IS *is; 7627 Mat *mat; 7628 PetscObjectState nonzerostate; 7629 Mat C; 7630 } EnvelopeData; 7631 7632 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7633 { 7634 EnvelopeData *edata = (EnvelopeData *)ptr; 7635 7636 PetscFunctionBegin; 7637 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7638 PetscCall(PetscFree(edata->is)); 7639 PetscCall(PetscFree(edata)); 7640 PetscFunctionReturn(PETSC_SUCCESS); 7641 } 7642 7643 /*@ 7644 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7645 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7646 7647 Collective 7648 7649 Input Parameter: 7650 . mat - the matrix 7651 7652 Level: intermediate 7653 7654 Notes: 7655 There can be zeros within the blocks 7656 7657 The blocks can overlap between processes, including laying on more than two processes 7658 7659 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7660 @*/ 7661 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7662 { 7663 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7664 PetscInt *diag, *odiag, sc; 7665 VecScatter scatter; 7666 PetscScalar *seqv; 7667 const PetscScalar *parv; 7668 const PetscInt *ia, *ja; 7669 PetscBool set, flag, done; 7670 Mat AA = mat, A; 7671 MPI_Comm comm; 7672 PetscMPIInt rank, size, tag; 7673 MPI_Status status; 7674 PetscContainer container; 7675 EnvelopeData *edata; 7676 Vec seq, par; 7677 IS isglobal; 7678 7679 PetscFunctionBegin; 7680 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7681 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7682 if (!set || !flag) { 7683 /* TODO: only needs nonzero structure of transpose */ 7684 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7685 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7686 } 7687 PetscCall(MatAIJGetLocalMat(AA, &A)); 7688 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7689 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7690 7691 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7692 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7693 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7694 PetscCallMPI(MPI_Comm_size(comm, &size)); 7695 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7696 7697 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7698 7699 if (rank > 0) { 7700 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7701 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7702 } 7703 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7704 for (i = 0; i < n; i++) { 7705 env = PetscMax(env, ja[ia[i + 1] - 1]); 7706 II = rstart + i; 7707 if (env == II) { 7708 starts[lblocks] = tbs; 7709 sizes[lblocks++] = 1 + II - tbs; 7710 tbs = 1 + II; 7711 } 7712 } 7713 if (rank < size - 1) { 7714 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7715 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7716 } 7717 7718 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7719 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7720 PetscCall(MatDestroy(&A)); 7721 7722 PetscCall(PetscNew(&edata)); 7723 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7724 edata->n = lblocks; 7725 /* create IS needed for extracting blocks from the original matrix */ 7726 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7727 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7728 7729 /* Create the resulting inverse matrix structure with preallocation information */ 7730 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7731 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7732 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7733 PetscCall(MatSetType(edata->C, MATAIJ)); 7734 7735 /* Communicate the start and end of each row, from each block to the correct rank */ 7736 /* TODO: Use PetscSF instead of VecScatter */ 7737 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7738 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7739 PetscCall(VecGetArrayWrite(seq, &seqv)); 7740 for (PetscInt i = 0; i < lblocks; i++) { 7741 for (PetscInt j = 0; j < sizes[i]; j++) { 7742 seqv[cnt] = starts[i]; 7743 seqv[cnt + 1] = starts[i] + sizes[i]; 7744 cnt += 2; 7745 } 7746 } 7747 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7748 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7749 sc -= cnt; 7750 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7751 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7752 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7753 PetscCall(ISDestroy(&isglobal)); 7754 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7755 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7756 PetscCall(VecScatterDestroy(&scatter)); 7757 PetscCall(VecDestroy(&seq)); 7758 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7759 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7760 PetscCall(VecGetArrayRead(par, &parv)); 7761 cnt = 0; 7762 PetscCall(MatGetSize(mat, NULL, &n)); 7763 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7764 PetscInt start, end, d = 0, od = 0; 7765 7766 start = (PetscInt)PetscRealPart(parv[cnt]); 7767 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7768 cnt += 2; 7769 7770 if (start < cstart) { 7771 od += cstart - start + n - cend; 7772 d += cend - cstart; 7773 } else if (start < cend) { 7774 od += n - cend; 7775 d += cend - start; 7776 } else od += n - start; 7777 if (end <= cstart) { 7778 od -= cstart - end + n - cend; 7779 d -= cend - cstart; 7780 } else if (end < cend) { 7781 od -= n - cend; 7782 d -= cend - end; 7783 } else od -= n - end; 7784 7785 odiag[i] = od; 7786 diag[i] = d; 7787 } 7788 PetscCall(VecRestoreArrayRead(par, &parv)); 7789 PetscCall(VecDestroy(&par)); 7790 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7791 PetscCall(PetscFree2(diag, odiag)); 7792 PetscCall(PetscFree2(sizes, starts)); 7793 7794 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7795 PetscCall(PetscContainerSetPointer(container, edata)); 7796 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7797 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7798 PetscCall(PetscObjectDereference((PetscObject)container)); 7799 PetscFunctionReturn(PETSC_SUCCESS); 7800 } 7801 7802 /*@ 7803 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7804 7805 Collective 7806 7807 Input Parameters: 7808 + A - the matrix 7809 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7810 7811 Output Parameter: 7812 . C - matrix with inverted block diagonal of `A` 7813 7814 Level: advanced 7815 7816 Note: 7817 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7818 7819 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7820 @*/ 7821 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7822 { 7823 PetscContainer container; 7824 EnvelopeData *edata; 7825 PetscObjectState nonzerostate; 7826 7827 PetscFunctionBegin; 7828 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7829 if (!container) { 7830 PetscCall(MatComputeVariableBlockEnvelope(A)); 7831 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7832 } 7833 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7834 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7835 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7836 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7837 7838 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7839 *C = edata->C; 7840 7841 for (PetscInt i = 0; i < edata->n; i++) { 7842 Mat D; 7843 PetscScalar *dvalues; 7844 7845 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7846 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7847 PetscCall(MatSeqDenseInvert(D)); 7848 PetscCall(MatDenseGetArray(D, &dvalues)); 7849 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7850 PetscCall(MatDestroy(&D)); 7851 } 7852 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7853 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7854 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7855 PetscFunctionReturn(PETSC_SUCCESS); 7856 } 7857 7858 /*@ 7859 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7860 7861 Not Collective 7862 7863 Input Parameters: 7864 + mat - the matrix 7865 . nblocks - the number of blocks on this process, each block can only exist on a single process 7866 - bsizes - the block sizes 7867 7868 Level: intermediate 7869 7870 Notes: 7871 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7872 7873 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. 7874 7875 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7876 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7877 @*/ 7878 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7879 { 7880 PetscInt ncnt = 0, nlocal; 7881 7882 PetscFunctionBegin; 7883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7884 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7885 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); 7886 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7887 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); 7888 PetscCall(PetscFree(mat->bsizes)); 7889 mat->nblocks = nblocks; 7890 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7891 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7892 PetscFunctionReturn(PETSC_SUCCESS); 7893 } 7894 7895 /*@C 7896 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7897 7898 Not Collective; No Fortran Support 7899 7900 Input Parameter: 7901 . mat - the matrix 7902 7903 Output Parameters: 7904 + nblocks - the number of blocks on this process 7905 - bsizes - the block sizes 7906 7907 Level: intermediate 7908 7909 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7910 @*/ 7911 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7912 { 7913 PetscFunctionBegin; 7914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7915 if (nblocks) *nblocks = mat->nblocks; 7916 if (bsizes) *bsizes = mat->bsizes; 7917 PetscFunctionReturn(PETSC_SUCCESS); 7918 } 7919 7920 /*@ 7921 MatSetBlockSizes - Sets the matrix block row and column sizes. 7922 7923 Logically Collective 7924 7925 Input Parameters: 7926 + mat - the matrix 7927 . rbs - row block size 7928 - cbs - column block size 7929 7930 Level: intermediate 7931 7932 Notes: 7933 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7934 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7935 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7936 7937 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7938 are compatible with the matrix local sizes. 7939 7940 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7941 7942 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7943 @*/ 7944 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7945 { 7946 PetscFunctionBegin; 7947 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7948 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7949 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7950 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7951 if (mat->rmap->refcnt) { 7952 ISLocalToGlobalMapping l2g = NULL; 7953 PetscLayout nmap = NULL; 7954 7955 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7956 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7957 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7958 mat->rmap = nmap; 7959 mat->rmap->mapping = l2g; 7960 } 7961 if (mat->cmap->refcnt) { 7962 ISLocalToGlobalMapping l2g = NULL; 7963 PetscLayout nmap = NULL; 7964 7965 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7966 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7967 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7968 mat->cmap = nmap; 7969 mat->cmap->mapping = l2g; 7970 } 7971 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7972 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7973 PetscFunctionReturn(PETSC_SUCCESS); 7974 } 7975 7976 /*@ 7977 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7978 7979 Logically Collective 7980 7981 Input Parameters: 7982 + mat - the matrix 7983 . fromRow - matrix from which to copy row block size 7984 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7985 7986 Level: developer 7987 7988 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7989 @*/ 7990 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7991 { 7992 PetscFunctionBegin; 7993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7994 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7995 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7996 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7997 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7998 PetscFunctionReturn(PETSC_SUCCESS); 7999 } 8000 8001 /*@ 8002 MatResidual - Default routine to calculate the residual r = b - Ax 8003 8004 Collective 8005 8006 Input Parameters: 8007 + mat - the matrix 8008 . b - the right-hand-side 8009 - x - the approximate solution 8010 8011 Output Parameter: 8012 . r - location to store the residual 8013 8014 Level: developer 8015 8016 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8017 @*/ 8018 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8019 { 8020 PetscFunctionBegin; 8021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8022 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8023 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8024 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8025 PetscValidType(mat, 1); 8026 MatCheckPreallocated(mat, 1); 8027 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8028 if (!mat->ops->residual) { 8029 PetscCall(MatMult(mat, x, r)); 8030 PetscCall(VecAYPX(r, -1.0, b)); 8031 } else { 8032 PetscUseTypeMethod(mat, residual, b, x, r); 8033 } 8034 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8035 PetscFunctionReturn(PETSC_SUCCESS); 8036 } 8037 8038 /*MC 8039 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8040 8041 Synopsis: 8042 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8043 8044 Not Collective 8045 8046 Input Parameters: 8047 + A - the matrix 8048 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8049 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8050 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8051 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8052 always used. 8053 8054 Output Parameters: 8055 + n - number of local rows in the (possibly compressed) matrix 8056 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8057 . ja - the column indices 8058 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8059 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8060 8061 Level: developer 8062 8063 Note: 8064 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8065 8066 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8067 M*/ 8068 8069 /*MC 8070 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8071 8072 Synopsis: 8073 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8074 8075 Not Collective 8076 8077 Input Parameters: 8078 + A - the matrix 8079 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8080 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8081 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8082 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8083 always used. 8084 . n - number of local rows in the (possibly compressed) matrix 8085 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8086 . ja - the column indices 8087 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8088 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8089 8090 Level: developer 8091 8092 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8093 M*/ 8094 8095 /*@C 8096 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8097 8098 Collective 8099 8100 Input Parameters: 8101 + mat - the matrix 8102 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8103 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8104 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8105 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8106 always used. 8107 8108 Output Parameters: 8109 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8110 . 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 8111 . ja - the column indices, use `NULL` if not needed 8112 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8113 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8114 8115 Level: developer 8116 8117 Notes: 8118 You CANNOT change any of the ia[] or ja[] values. 8119 8120 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8121 8122 Fortran Notes: 8123 Use 8124 .vb 8125 PetscInt, pointer :: ia(:),ja(:) 8126 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8127 ! Access the ith and jth entries via ia(i) and ja(j) 8128 .ve 8129 8130 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8131 8132 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8133 @*/ 8134 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8135 { 8136 PetscFunctionBegin; 8137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8138 PetscValidType(mat, 1); 8139 if (n) PetscAssertPointer(n, 5); 8140 if (ia) PetscAssertPointer(ia, 6); 8141 if (ja) PetscAssertPointer(ja, 7); 8142 if (done) PetscAssertPointer(done, 8); 8143 MatCheckPreallocated(mat, 1); 8144 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8145 else { 8146 if (done) *done = PETSC_TRUE; 8147 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8148 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8149 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8150 } 8151 PetscFunctionReturn(PETSC_SUCCESS); 8152 } 8153 8154 /*@C 8155 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8156 8157 Collective 8158 8159 Input Parameters: 8160 + mat - the matrix 8161 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8162 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8163 symmetrized 8164 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8165 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8166 always used. 8167 . n - number of columns in the (possibly compressed) matrix 8168 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8169 - ja - the row indices 8170 8171 Output Parameter: 8172 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8173 8174 Level: developer 8175 8176 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8177 @*/ 8178 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8179 { 8180 PetscFunctionBegin; 8181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8182 PetscValidType(mat, 1); 8183 PetscAssertPointer(n, 5); 8184 if (ia) PetscAssertPointer(ia, 6); 8185 if (ja) PetscAssertPointer(ja, 7); 8186 PetscAssertPointer(done, 8); 8187 MatCheckPreallocated(mat, 1); 8188 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8189 else { 8190 *done = PETSC_TRUE; 8191 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8192 } 8193 PetscFunctionReturn(PETSC_SUCCESS); 8194 } 8195 8196 /*@C 8197 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8198 8199 Collective 8200 8201 Input Parameters: 8202 + mat - the matrix 8203 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8204 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8205 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8206 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8207 always used. 8208 . n - size of (possibly compressed) matrix 8209 . ia - the row pointers 8210 - ja - the column indices 8211 8212 Output Parameter: 8213 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8214 8215 Level: developer 8216 8217 Note: 8218 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8219 us of the array after it has been restored. If you pass `NULL`, it will 8220 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8221 8222 Fortran Note: 8223 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8224 8225 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8226 @*/ 8227 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8228 { 8229 PetscFunctionBegin; 8230 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8231 PetscValidType(mat, 1); 8232 if (ia) PetscAssertPointer(ia, 6); 8233 if (ja) PetscAssertPointer(ja, 7); 8234 if (done) PetscAssertPointer(done, 8); 8235 MatCheckPreallocated(mat, 1); 8236 8237 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8238 else { 8239 if (done) *done = PETSC_TRUE; 8240 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8241 if (n) *n = 0; 8242 if (ia) *ia = NULL; 8243 if (ja) *ja = NULL; 8244 } 8245 PetscFunctionReturn(PETSC_SUCCESS); 8246 } 8247 8248 /*@C 8249 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8250 8251 Collective 8252 8253 Input Parameters: 8254 + mat - the matrix 8255 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8256 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8257 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8258 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8259 always used. 8260 8261 Output Parameters: 8262 + n - size of (possibly compressed) matrix 8263 . ia - the column pointers 8264 . ja - the row indices 8265 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8266 8267 Level: developer 8268 8269 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8270 @*/ 8271 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8272 { 8273 PetscFunctionBegin; 8274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8275 PetscValidType(mat, 1); 8276 if (ia) PetscAssertPointer(ia, 6); 8277 if (ja) PetscAssertPointer(ja, 7); 8278 PetscAssertPointer(done, 8); 8279 MatCheckPreallocated(mat, 1); 8280 8281 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8282 else { 8283 *done = PETSC_TRUE; 8284 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8285 if (n) *n = 0; 8286 if (ia) *ia = NULL; 8287 if (ja) *ja = NULL; 8288 } 8289 PetscFunctionReturn(PETSC_SUCCESS); 8290 } 8291 8292 /*@ 8293 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8294 `MatGetColumnIJ()`. 8295 8296 Collective 8297 8298 Input Parameters: 8299 + mat - the matrix 8300 . ncolors - maximum color value 8301 . n - number of entries in colorarray 8302 - colorarray - array indicating color for each column 8303 8304 Output Parameter: 8305 . iscoloring - coloring generated using colorarray information 8306 8307 Level: developer 8308 8309 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8310 @*/ 8311 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8312 { 8313 PetscFunctionBegin; 8314 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8315 PetscValidType(mat, 1); 8316 PetscAssertPointer(colorarray, 4); 8317 PetscAssertPointer(iscoloring, 5); 8318 MatCheckPreallocated(mat, 1); 8319 8320 if (!mat->ops->coloringpatch) { 8321 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8322 } else { 8323 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8324 } 8325 PetscFunctionReturn(PETSC_SUCCESS); 8326 } 8327 8328 /*@ 8329 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8330 8331 Logically Collective 8332 8333 Input Parameter: 8334 . mat - the factored matrix to be reset 8335 8336 Level: developer 8337 8338 Notes: 8339 This routine should be used only with factored matrices formed by in-place 8340 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8341 format). This option can save memory, for example, when solving nonlinear 8342 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8343 ILU(0) preconditioner. 8344 8345 One can specify in-place ILU(0) factorization by calling 8346 .vb 8347 PCType(pc,PCILU); 8348 PCFactorSeUseInPlace(pc); 8349 .ve 8350 or by using the options -pc_type ilu -pc_factor_in_place 8351 8352 In-place factorization ILU(0) can also be used as a local 8353 solver for the blocks within the block Jacobi or additive Schwarz 8354 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8355 for details on setting local solver options. 8356 8357 Most users should employ the `KSP` interface for linear solvers 8358 instead of working directly with matrix algebra routines such as this. 8359 See, e.g., `KSPCreate()`. 8360 8361 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8362 @*/ 8363 PetscErrorCode MatSetUnfactored(Mat mat) 8364 { 8365 PetscFunctionBegin; 8366 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8367 PetscValidType(mat, 1); 8368 MatCheckPreallocated(mat, 1); 8369 mat->factortype = MAT_FACTOR_NONE; 8370 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8371 PetscUseTypeMethod(mat, setunfactored); 8372 PetscFunctionReturn(PETSC_SUCCESS); 8373 } 8374 8375 /*MC 8376 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8377 8378 Synopsis: 8379 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8380 8381 Not Collective 8382 8383 Input Parameter: 8384 . x - matrix 8385 8386 Output Parameters: 8387 + xx_v - the Fortran pointer to the array 8388 - ierr - error code 8389 8390 Example of Usage: 8391 .vb 8392 PetscScalar, pointer xx_v(:,:) 8393 .... 8394 call MatDenseGetArrayF90(x,xx_v,ierr) 8395 a = xx_v(3) 8396 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8397 .ve 8398 8399 Level: advanced 8400 8401 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8402 M*/ 8403 8404 /*MC 8405 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8406 accessed with `MatDenseGetArrayF90()`. 8407 8408 Synopsis: 8409 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8410 8411 Not Collective 8412 8413 Input Parameters: 8414 + x - matrix 8415 - xx_v - the Fortran90 pointer to the array 8416 8417 Output Parameter: 8418 . ierr - error code 8419 8420 Example of Usage: 8421 .vb 8422 PetscScalar, pointer xx_v(:,:) 8423 .... 8424 call MatDenseGetArrayF90(x,xx_v,ierr) 8425 a = xx_v(3) 8426 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8427 .ve 8428 8429 Level: advanced 8430 8431 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8432 M*/ 8433 8434 /*MC 8435 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8436 8437 Synopsis: 8438 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8439 8440 Not Collective 8441 8442 Input Parameter: 8443 . x - matrix 8444 8445 Output Parameters: 8446 + xx_v - the Fortran pointer to the array 8447 - ierr - error code 8448 8449 Example of Usage: 8450 .vb 8451 PetscScalar, pointer xx_v(:) 8452 .... 8453 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8454 a = xx_v(3) 8455 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8456 .ve 8457 8458 Level: advanced 8459 8460 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8461 M*/ 8462 8463 /*MC 8464 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8465 accessed with `MatSeqAIJGetArrayF90()`. 8466 8467 Synopsis: 8468 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8469 8470 Not Collective 8471 8472 Input Parameters: 8473 + x - matrix 8474 - xx_v - the Fortran90 pointer to the array 8475 8476 Output Parameter: 8477 . ierr - error code 8478 8479 Example of Usage: 8480 .vb 8481 PetscScalar, pointer xx_v(:) 8482 .... 8483 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8484 a = xx_v(3) 8485 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8486 .ve 8487 8488 Level: advanced 8489 8490 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8491 M*/ 8492 8493 /*@ 8494 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8495 as the original matrix. 8496 8497 Collective 8498 8499 Input Parameters: 8500 + mat - the original matrix 8501 . isrow - parallel `IS` containing the rows this processor should obtain 8502 . 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. 8503 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8504 8505 Output Parameter: 8506 . newmat - the new submatrix, of the same type as the original matrix 8507 8508 Level: advanced 8509 8510 Notes: 8511 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8512 8513 Some matrix types place restrictions on the row and column indices, such 8514 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; 8515 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8516 8517 The index sets may not have duplicate entries. 8518 8519 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8520 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8521 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8522 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8523 you are finished using it. 8524 8525 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8526 the input matrix. 8527 8528 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8529 8530 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8531 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8532 8533 Example usage: 8534 Consider the following 8x8 matrix with 34 non-zero values, that is 8535 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8536 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8537 as follows 8538 .vb 8539 1 2 0 | 0 3 0 | 0 4 8540 Proc0 0 5 6 | 7 0 0 | 8 0 8541 9 0 10 | 11 0 0 | 12 0 8542 ------------------------------------- 8543 13 0 14 | 15 16 17 | 0 0 8544 Proc1 0 18 0 | 19 20 21 | 0 0 8545 0 0 0 | 22 23 0 | 24 0 8546 ------------------------------------- 8547 Proc2 25 26 27 | 0 0 28 | 29 0 8548 30 0 0 | 31 32 33 | 0 34 8549 .ve 8550 8551 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8552 8553 .vb 8554 2 0 | 0 3 0 | 0 8555 Proc0 5 6 | 7 0 0 | 8 8556 ------------------------------- 8557 Proc1 18 0 | 19 20 21 | 0 8558 ------------------------------- 8559 Proc2 26 27 | 0 0 28 | 29 8560 0 0 | 31 32 33 | 0 8561 .ve 8562 8563 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8564 @*/ 8565 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8566 { 8567 PetscMPIInt size; 8568 Mat *local; 8569 IS iscoltmp; 8570 PetscBool flg; 8571 8572 PetscFunctionBegin; 8573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8574 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8575 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8576 PetscAssertPointer(newmat, 5); 8577 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8578 PetscValidType(mat, 1); 8579 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8580 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8581 8582 MatCheckPreallocated(mat, 1); 8583 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8584 8585 if (!iscol || isrow == iscol) { 8586 PetscBool stride; 8587 PetscMPIInt grabentirematrix = 0, grab; 8588 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8589 if (stride) { 8590 PetscInt first, step, n, rstart, rend; 8591 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8592 if (step == 1) { 8593 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8594 if (rstart == first) { 8595 PetscCall(ISGetLocalSize(isrow, &n)); 8596 if (n == rend - rstart) grabentirematrix = 1; 8597 } 8598 } 8599 } 8600 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8601 if (grab) { 8602 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8603 if (cll == MAT_INITIAL_MATRIX) { 8604 *newmat = mat; 8605 PetscCall(PetscObjectReference((PetscObject)mat)); 8606 } 8607 PetscFunctionReturn(PETSC_SUCCESS); 8608 } 8609 } 8610 8611 if (!iscol) { 8612 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8613 } else { 8614 iscoltmp = iscol; 8615 } 8616 8617 /* if original matrix is on just one processor then use submatrix generated */ 8618 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8619 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8620 goto setproperties; 8621 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8622 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8623 *newmat = *local; 8624 PetscCall(PetscFree(local)); 8625 goto setproperties; 8626 } else if (!mat->ops->createsubmatrix) { 8627 /* Create a new matrix type that implements the operation using the full matrix */ 8628 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8629 switch (cll) { 8630 case MAT_INITIAL_MATRIX: 8631 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8632 break; 8633 case MAT_REUSE_MATRIX: 8634 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8635 break; 8636 default: 8637 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8638 } 8639 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8640 goto setproperties; 8641 } 8642 8643 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8644 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8645 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8646 8647 setproperties: 8648 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8649 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8650 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8651 } 8652 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8653 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8654 PetscFunctionReturn(PETSC_SUCCESS); 8655 } 8656 8657 /*@ 8658 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8659 8660 Not Collective 8661 8662 Input Parameters: 8663 + A - the matrix we wish to propagate options from 8664 - B - the matrix we wish to propagate options to 8665 8666 Level: beginner 8667 8668 Note: 8669 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8670 8671 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8672 @*/ 8673 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8674 { 8675 PetscFunctionBegin; 8676 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8677 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8678 B->symmetry_eternal = A->symmetry_eternal; 8679 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8680 B->symmetric = A->symmetric; 8681 B->structurally_symmetric = A->structurally_symmetric; 8682 B->spd = A->spd; 8683 B->hermitian = A->hermitian; 8684 PetscFunctionReturn(PETSC_SUCCESS); 8685 } 8686 8687 /*@ 8688 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8689 used during the assembly process to store values that belong to 8690 other processors. 8691 8692 Not Collective 8693 8694 Input Parameters: 8695 + mat - the matrix 8696 . size - the initial size of the stash. 8697 - bsize - the initial size of the block-stash(if used). 8698 8699 Options Database Keys: 8700 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8701 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8702 8703 Level: intermediate 8704 8705 Notes: 8706 The block-stash is used for values set with `MatSetValuesBlocked()` while 8707 the stash is used for values set with `MatSetValues()` 8708 8709 Run with the option -info and look for output of the form 8710 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8711 to determine the appropriate value, MM, to use for size and 8712 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8713 to determine the value, BMM to use for bsize 8714 8715 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8716 @*/ 8717 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8718 { 8719 PetscFunctionBegin; 8720 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8721 PetscValidType(mat, 1); 8722 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8723 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8724 PetscFunctionReturn(PETSC_SUCCESS); 8725 } 8726 8727 /*@ 8728 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8729 the matrix 8730 8731 Neighbor-wise Collective 8732 8733 Input Parameters: 8734 + A - the matrix 8735 . x - the vector to be multiplied by the interpolation operator 8736 - y - the vector to be added to the result 8737 8738 Output Parameter: 8739 . w - the resulting vector 8740 8741 Level: intermediate 8742 8743 Notes: 8744 `w` may be the same vector as `y`. 8745 8746 This allows one to use either the restriction or interpolation (its transpose) 8747 matrix to do the interpolation 8748 8749 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8750 @*/ 8751 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8752 { 8753 PetscInt M, N, Ny; 8754 8755 PetscFunctionBegin; 8756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8757 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8758 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8759 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8760 PetscCall(MatGetSize(A, &M, &N)); 8761 PetscCall(VecGetSize(y, &Ny)); 8762 if (M == Ny) { 8763 PetscCall(MatMultAdd(A, x, y, w)); 8764 } else { 8765 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8766 } 8767 PetscFunctionReturn(PETSC_SUCCESS); 8768 } 8769 8770 /*@ 8771 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8772 the matrix 8773 8774 Neighbor-wise Collective 8775 8776 Input Parameters: 8777 + A - the matrix 8778 - x - the vector to be interpolated 8779 8780 Output Parameter: 8781 . y - the resulting vector 8782 8783 Level: intermediate 8784 8785 Note: 8786 This allows one to use either the restriction or interpolation (its transpose) 8787 matrix to do the interpolation 8788 8789 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8790 @*/ 8791 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8792 { 8793 PetscInt M, N, Ny; 8794 8795 PetscFunctionBegin; 8796 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8797 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8798 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8799 PetscCall(MatGetSize(A, &M, &N)); 8800 PetscCall(VecGetSize(y, &Ny)); 8801 if (M == Ny) { 8802 PetscCall(MatMult(A, x, y)); 8803 } else { 8804 PetscCall(MatMultTranspose(A, x, y)); 8805 } 8806 PetscFunctionReturn(PETSC_SUCCESS); 8807 } 8808 8809 /*@ 8810 MatRestrict - $y = A*x$ or $A^T*x$ 8811 8812 Neighbor-wise Collective 8813 8814 Input Parameters: 8815 + A - the matrix 8816 - x - the vector to be restricted 8817 8818 Output Parameter: 8819 . y - the resulting vector 8820 8821 Level: intermediate 8822 8823 Note: 8824 This allows one to use either the restriction or interpolation (its transpose) 8825 matrix to do the restriction 8826 8827 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8828 @*/ 8829 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8830 { 8831 PetscInt M, N, Nx; 8832 8833 PetscFunctionBegin; 8834 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8835 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8836 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8837 PetscCall(MatGetSize(A, &M, &N)); 8838 PetscCall(VecGetSize(x, &Nx)); 8839 if (M == Nx) { 8840 PetscCall(MatMultTranspose(A, x, y)); 8841 } else { 8842 PetscCall(MatMult(A, x, y)); 8843 } 8844 PetscFunctionReturn(PETSC_SUCCESS); 8845 } 8846 8847 /*@ 8848 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8849 8850 Neighbor-wise Collective 8851 8852 Input Parameters: 8853 + A - the matrix 8854 . x - the input dense matrix to be multiplied 8855 - w - the input dense matrix to be added to the result 8856 8857 Output Parameter: 8858 . y - the output dense matrix 8859 8860 Level: intermediate 8861 8862 Note: 8863 This allows one to use either the restriction or interpolation (its transpose) 8864 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8865 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8866 8867 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8868 @*/ 8869 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8870 { 8871 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8872 PetscBool trans = PETSC_TRUE; 8873 MatReuse reuse = MAT_INITIAL_MATRIX; 8874 8875 PetscFunctionBegin; 8876 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8877 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8878 PetscValidType(x, 2); 8879 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8880 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8881 PetscCall(MatGetSize(A, &M, &N)); 8882 PetscCall(MatGetSize(x, &Mx, &Nx)); 8883 if (N == Mx) trans = PETSC_FALSE; 8884 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); 8885 Mo = trans ? N : M; 8886 if (*y) { 8887 PetscCall(MatGetSize(*y, &My, &Ny)); 8888 if (Mo == My && Nx == Ny) { 8889 reuse = MAT_REUSE_MATRIX; 8890 } else { 8891 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); 8892 PetscCall(MatDestroy(y)); 8893 } 8894 } 8895 8896 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8897 PetscBool flg; 8898 8899 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8900 if (w) { 8901 PetscInt My, Ny, Mw, Nw; 8902 8903 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8904 PetscCall(MatGetSize(*y, &My, &Ny)); 8905 PetscCall(MatGetSize(w, &Mw, &Nw)); 8906 if (!flg || My != Mw || Ny != Nw) w = NULL; 8907 } 8908 if (!w) { 8909 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8910 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8911 PetscCall(PetscObjectDereference((PetscObject)w)); 8912 } else { 8913 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8914 } 8915 } 8916 if (!trans) { 8917 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8918 } else { 8919 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8920 } 8921 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8922 PetscFunctionReturn(PETSC_SUCCESS); 8923 } 8924 8925 /*@ 8926 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8927 8928 Neighbor-wise Collective 8929 8930 Input Parameters: 8931 + A - the matrix 8932 - x - the input dense matrix 8933 8934 Output Parameter: 8935 . y - the output dense matrix 8936 8937 Level: intermediate 8938 8939 Note: 8940 This allows one to use either the restriction or interpolation (its transpose) 8941 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8942 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8943 8944 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8945 @*/ 8946 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8947 { 8948 PetscFunctionBegin; 8949 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8950 PetscFunctionReturn(PETSC_SUCCESS); 8951 } 8952 8953 /*@ 8954 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8955 8956 Neighbor-wise Collective 8957 8958 Input Parameters: 8959 + A - the matrix 8960 - x - the input dense matrix 8961 8962 Output Parameter: 8963 . y - the output dense matrix 8964 8965 Level: intermediate 8966 8967 Note: 8968 This allows one to use either the restriction or interpolation (its transpose) 8969 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8970 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8971 8972 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8973 @*/ 8974 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8975 { 8976 PetscFunctionBegin; 8977 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8978 PetscFunctionReturn(PETSC_SUCCESS); 8979 } 8980 8981 /*@ 8982 MatGetNullSpace - retrieves the null space of a matrix. 8983 8984 Logically Collective 8985 8986 Input Parameters: 8987 + mat - the matrix 8988 - nullsp - the null space object 8989 8990 Level: developer 8991 8992 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8993 @*/ 8994 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8995 { 8996 PetscFunctionBegin; 8997 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8998 PetscAssertPointer(nullsp, 2); 8999 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 9000 PetscFunctionReturn(PETSC_SUCCESS); 9001 } 9002 9003 /*@C 9004 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9005 9006 Logically Collective 9007 9008 Input Parameters: 9009 + n - the number of matrices 9010 - mat - the array of matrices 9011 9012 Output Parameters: 9013 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9014 9015 Level: developer 9016 9017 Note: 9018 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9019 9020 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9021 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9022 @*/ 9023 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9024 { 9025 PetscFunctionBegin; 9026 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9027 PetscAssertPointer(mat, 2); 9028 PetscAssertPointer(nullsp, 3); 9029 9030 PetscCall(PetscCalloc1(3 * n, nullsp)); 9031 for (PetscInt i = 0; i < n; i++) { 9032 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9033 (*nullsp)[i] = mat[i]->nullsp; 9034 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9035 (*nullsp)[n + i] = mat[i]->nearnullsp; 9036 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9037 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9038 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9039 } 9040 PetscFunctionReturn(PETSC_SUCCESS); 9041 } 9042 9043 /*@C 9044 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9045 9046 Logically Collective 9047 9048 Input Parameters: 9049 + n - the number of matrices 9050 . mat - the array of matrices 9051 - nullsp - an array of null spaces 9052 9053 Level: developer 9054 9055 Note: 9056 Call `MatGetNullSpaces()` to create `nullsp` 9057 9058 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9059 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9060 @*/ 9061 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9062 { 9063 PetscFunctionBegin; 9064 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9065 PetscAssertPointer(mat, 2); 9066 PetscAssertPointer(nullsp, 3); 9067 PetscAssertPointer(*nullsp, 3); 9068 9069 for (PetscInt i = 0; i < n; i++) { 9070 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9071 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9072 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9073 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9074 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9075 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9076 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9077 } 9078 PetscCall(PetscFree(*nullsp)); 9079 PetscFunctionReturn(PETSC_SUCCESS); 9080 } 9081 9082 /*@ 9083 MatSetNullSpace - attaches a null space to a matrix. 9084 9085 Logically Collective 9086 9087 Input Parameters: 9088 + mat - the matrix 9089 - nullsp - the null space object 9090 9091 Level: advanced 9092 9093 Notes: 9094 This null space is used by the `KSP` linear solvers to solve singular systems. 9095 9096 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` 9097 9098 For inconsistent singular systems (linear systems where the right-hand side is not in the range of the operator) the `KSP` residuals will not converge to 9099 to zero but the linear system will still be solved in a least squares sense. 9100 9101 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9102 the domain of a matrix A (from $R^n$ to $R^m$ (m rows, n columns) $R^n$ = the direct sum of the null space of A, n(A), + the range of $A^T$, $R(A^T)$. 9103 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 9104 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 9105 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$). 9106 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9107 9108 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9109 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9110 routine also automatically calls `MatSetTransposeNullSpace()`. 9111 9112 The user should call `MatNullSpaceDestroy()`. 9113 9114 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9115 `KSPSetPCSide()` 9116 @*/ 9117 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9118 { 9119 PetscFunctionBegin; 9120 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9121 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9122 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9123 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9124 mat->nullsp = nullsp; 9125 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9126 PetscFunctionReturn(PETSC_SUCCESS); 9127 } 9128 9129 /*@ 9130 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9131 9132 Logically Collective 9133 9134 Input Parameters: 9135 + mat - the matrix 9136 - nullsp - the null space object 9137 9138 Level: developer 9139 9140 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9141 @*/ 9142 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9143 { 9144 PetscFunctionBegin; 9145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9146 PetscValidType(mat, 1); 9147 PetscAssertPointer(nullsp, 2); 9148 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9149 PetscFunctionReturn(PETSC_SUCCESS); 9150 } 9151 9152 /*@ 9153 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9154 9155 Logically Collective 9156 9157 Input Parameters: 9158 + mat - the matrix 9159 - nullsp - the null space object 9160 9161 Level: advanced 9162 9163 Notes: 9164 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9165 9166 See `MatSetNullSpace()` 9167 9168 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9169 @*/ 9170 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9171 { 9172 PetscFunctionBegin; 9173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9174 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9175 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9176 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9177 mat->transnullsp = nullsp; 9178 PetscFunctionReturn(PETSC_SUCCESS); 9179 } 9180 9181 /*@ 9182 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9183 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9184 9185 Logically Collective 9186 9187 Input Parameters: 9188 + mat - the matrix 9189 - nullsp - the null space object 9190 9191 Level: advanced 9192 9193 Notes: 9194 Overwrites any previous near null space that may have been attached 9195 9196 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9197 9198 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9199 @*/ 9200 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9201 { 9202 PetscFunctionBegin; 9203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9204 PetscValidType(mat, 1); 9205 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9206 MatCheckPreallocated(mat, 1); 9207 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9208 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9209 mat->nearnullsp = nullsp; 9210 PetscFunctionReturn(PETSC_SUCCESS); 9211 } 9212 9213 /*@ 9214 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9215 9216 Not Collective 9217 9218 Input Parameter: 9219 . mat - the matrix 9220 9221 Output Parameter: 9222 . nullsp - the null space object, `NULL` if not set 9223 9224 Level: advanced 9225 9226 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9227 @*/ 9228 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9229 { 9230 PetscFunctionBegin; 9231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9232 PetscValidType(mat, 1); 9233 PetscAssertPointer(nullsp, 2); 9234 MatCheckPreallocated(mat, 1); 9235 *nullsp = mat->nearnullsp; 9236 PetscFunctionReturn(PETSC_SUCCESS); 9237 } 9238 9239 /*@ 9240 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9241 9242 Collective 9243 9244 Input Parameters: 9245 + mat - the matrix 9246 . row - row/column permutation 9247 - info - information on desired factorization process 9248 9249 Level: developer 9250 9251 Notes: 9252 Probably really in-place only when level of fill is zero, otherwise allocates 9253 new space to store factored matrix and deletes previous memory. 9254 9255 Most users should employ the `KSP` interface for linear solvers 9256 instead of working directly with matrix algebra routines such as this. 9257 See, e.g., `KSPCreate()`. 9258 9259 Developer Note: 9260 The Fortran interface is not autogenerated as the 9261 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9262 9263 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9264 @*/ 9265 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9266 { 9267 PetscFunctionBegin; 9268 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9269 PetscValidType(mat, 1); 9270 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9271 PetscAssertPointer(info, 3); 9272 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9275 MatCheckPreallocated(mat, 1); 9276 PetscUseTypeMethod(mat, iccfactor, row, info); 9277 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9278 PetscFunctionReturn(PETSC_SUCCESS); 9279 } 9280 9281 /*@ 9282 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9283 ghosted ones. 9284 9285 Not Collective 9286 9287 Input Parameters: 9288 + mat - the matrix 9289 - diag - the diagonal values, including ghost ones 9290 9291 Level: developer 9292 9293 Notes: 9294 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9295 9296 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9297 9298 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9299 @*/ 9300 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9301 { 9302 PetscMPIInt size; 9303 9304 PetscFunctionBegin; 9305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9306 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9307 PetscValidType(mat, 1); 9308 9309 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9310 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9311 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9312 if (size == 1) { 9313 PetscInt n, m; 9314 PetscCall(VecGetSize(diag, &n)); 9315 PetscCall(MatGetSize(mat, NULL, &m)); 9316 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9317 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9318 } else { 9319 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9320 } 9321 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9322 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9323 PetscFunctionReturn(PETSC_SUCCESS); 9324 } 9325 9326 /*@ 9327 MatGetInertia - Gets the inertia from a factored matrix 9328 9329 Collective 9330 9331 Input Parameter: 9332 . mat - the matrix 9333 9334 Output Parameters: 9335 + nneg - number of negative eigenvalues 9336 . nzero - number of zero eigenvalues 9337 - npos - number of positive eigenvalues 9338 9339 Level: advanced 9340 9341 Note: 9342 Matrix must have been factored by `MatCholeskyFactor()` 9343 9344 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9345 @*/ 9346 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9347 { 9348 PetscFunctionBegin; 9349 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9350 PetscValidType(mat, 1); 9351 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9352 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9353 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9354 PetscFunctionReturn(PETSC_SUCCESS); 9355 } 9356 9357 /*@C 9358 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9359 9360 Neighbor-wise Collective 9361 9362 Input Parameters: 9363 + mat - the factored matrix obtained with `MatGetFactor()` 9364 - b - the right-hand-side vectors 9365 9366 Output Parameter: 9367 . x - the result vectors 9368 9369 Level: developer 9370 9371 Note: 9372 The vectors `b` and `x` cannot be the same. I.e., one cannot 9373 call `MatSolves`(A,x,x). 9374 9375 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9376 @*/ 9377 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9378 { 9379 PetscFunctionBegin; 9380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9381 PetscValidType(mat, 1); 9382 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9383 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9384 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9385 9386 MatCheckPreallocated(mat, 1); 9387 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9388 PetscUseTypeMethod(mat, solves, b, x); 9389 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9390 PetscFunctionReturn(PETSC_SUCCESS); 9391 } 9392 9393 /*@ 9394 MatIsSymmetric - Test whether a matrix is symmetric 9395 9396 Collective 9397 9398 Input Parameters: 9399 + A - the matrix to test 9400 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9401 9402 Output Parameter: 9403 . flg - the result 9404 9405 Level: intermediate 9406 9407 Notes: 9408 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9409 9410 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9411 9412 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9413 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9414 9415 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9416 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9417 @*/ 9418 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9419 { 9420 PetscFunctionBegin; 9421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9422 PetscAssertPointer(flg, 3); 9423 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9424 else { 9425 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9426 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9427 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9428 } 9429 PetscFunctionReturn(PETSC_SUCCESS); 9430 } 9431 9432 /*@ 9433 MatIsHermitian - Test whether a matrix is Hermitian 9434 9435 Collective 9436 9437 Input Parameters: 9438 + A - the matrix to test 9439 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9440 9441 Output Parameter: 9442 . flg - the result 9443 9444 Level: intermediate 9445 9446 Notes: 9447 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9448 9449 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9450 9451 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9452 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9453 9454 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9455 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9456 @*/ 9457 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9458 { 9459 PetscFunctionBegin; 9460 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9461 PetscAssertPointer(flg, 3); 9462 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9463 else { 9464 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9465 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9466 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9467 } 9468 PetscFunctionReturn(PETSC_SUCCESS); 9469 } 9470 9471 /*@ 9472 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9473 9474 Not Collective 9475 9476 Input Parameter: 9477 . A - the matrix to check 9478 9479 Output Parameters: 9480 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9481 - flg - the result (only valid if set is `PETSC_TRUE`) 9482 9483 Level: advanced 9484 9485 Notes: 9486 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9487 if you want it explicitly checked 9488 9489 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9490 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9491 9492 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9493 @*/ 9494 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9495 { 9496 PetscFunctionBegin; 9497 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9498 PetscAssertPointer(set, 2); 9499 PetscAssertPointer(flg, 3); 9500 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9501 *set = PETSC_TRUE; 9502 *flg = PetscBool3ToBool(A->symmetric); 9503 } else { 9504 *set = PETSC_FALSE; 9505 } 9506 PetscFunctionReturn(PETSC_SUCCESS); 9507 } 9508 9509 /*@ 9510 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9511 9512 Not Collective 9513 9514 Input Parameter: 9515 . A - the matrix to check 9516 9517 Output Parameters: 9518 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9519 - flg - the result (only valid if set is `PETSC_TRUE`) 9520 9521 Level: advanced 9522 9523 Notes: 9524 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9525 9526 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9527 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9528 9529 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9530 @*/ 9531 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9532 { 9533 PetscFunctionBegin; 9534 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9535 PetscAssertPointer(set, 2); 9536 PetscAssertPointer(flg, 3); 9537 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9538 *set = PETSC_TRUE; 9539 *flg = PetscBool3ToBool(A->spd); 9540 } else { 9541 *set = PETSC_FALSE; 9542 } 9543 PetscFunctionReturn(PETSC_SUCCESS); 9544 } 9545 9546 /*@ 9547 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9548 9549 Not Collective 9550 9551 Input Parameter: 9552 . A - the matrix to check 9553 9554 Output Parameters: 9555 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9556 - flg - the result (only valid if set is `PETSC_TRUE`) 9557 9558 Level: advanced 9559 9560 Notes: 9561 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9562 if you want it explicitly checked 9563 9564 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9565 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9566 9567 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9568 @*/ 9569 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9570 { 9571 PetscFunctionBegin; 9572 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9573 PetscAssertPointer(set, 2); 9574 PetscAssertPointer(flg, 3); 9575 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9576 *set = PETSC_TRUE; 9577 *flg = PetscBool3ToBool(A->hermitian); 9578 } else { 9579 *set = PETSC_FALSE; 9580 } 9581 PetscFunctionReturn(PETSC_SUCCESS); 9582 } 9583 9584 /*@ 9585 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9586 9587 Collective 9588 9589 Input Parameter: 9590 . A - the matrix to test 9591 9592 Output Parameter: 9593 . flg - the result 9594 9595 Level: intermediate 9596 9597 Notes: 9598 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9599 9600 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 9601 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9602 9603 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9604 @*/ 9605 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9606 { 9607 PetscFunctionBegin; 9608 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9609 PetscAssertPointer(flg, 2); 9610 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9611 *flg = PetscBool3ToBool(A->structurally_symmetric); 9612 } else { 9613 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9614 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9615 } 9616 PetscFunctionReturn(PETSC_SUCCESS); 9617 } 9618 9619 /*@ 9620 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9621 9622 Not Collective 9623 9624 Input Parameter: 9625 . A - the matrix to check 9626 9627 Output Parameters: 9628 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9629 - flg - the result (only valid if set is PETSC_TRUE) 9630 9631 Level: advanced 9632 9633 Notes: 9634 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 9635 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9636 9637 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9638 9639 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9640 @*/ 9641 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9642 { 9643 PetscFunctionBegin; 9644 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9645 PetscAssertPointer(set, 2); 9646 PetscAssertPointer(flg, 3); 9647 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9648 *set = PETSC_TRUE; 9649 *flg = PetscBool3ToBool(A->structurally_symmetric); 9650 } else { 9651 *set = PETSC_FALSE; 9652 } 9653 PetscFunctionReturn(PETSC_SUCCESS); 9654 } 9655 9656 /*@ 9657 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9658 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9659 9660 Not Collective 9661 9662 Input Parameter: 9663 . mat - the matrix 9664 9665 Output Parameters: 9666 + nstash - the size of the stash 9667 . reallocs - the number of additional mallocs incurred. 9668 . bnstash - the size of the block stash 9669 - breallocs - the number of additional mallocs incurred.in the block stash 9670 9671 Level: advanced 9672 9673 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9674 @*/ 9675 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9676 { 9677 PetscFunctionBegin; 9678 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9679 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9680 PetscFunctionReturn(PETSC_SUCCESS); 9681 } 9682 9683 /*@ 9684 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9685 parallel layout, `PetscLayout` for rows and columns 9686 9687 Collective 9688 9689 Input Parameter: 9690 . mat - the matrix 9691 9692 Output Parameters: 9693 + right - (optional) vector that the matrix can be multiplied against 9694 - left - (optional) vector that the matrix vector product can be stored in 9695 9696 Level: advanced 9697 9698 Notes: 9699 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()`. 9700 9701 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9702 9703 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9704 @*/ 9705 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9706 { 9707 PetscFunctionBegin; 9708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9709 PetscValidType(mat, 1); 9710 if (mat->ops->getvecs) { 9711 PetscUseTypeMethod(mat, getvecs, right, left); 9712 } else { 9713 if (right) { 9714 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9715 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9716 PetscCall(VecSetType(*right, mat->defaultvectype)); 9717 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9718 if (mat->boundtocpu && mat->bindingpropagates) { 9719 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9720 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9721 } 9722 #endif 9723 } 9724 if (left) { 9725 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9726 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9727 PetscCall(VecSetType(*left, mat->defaultvectype)); 9728 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9729 if (mat->boundtocpu && mat->bindingpropagates) { 9730 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9731 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9732 } 9733 #endif 9734 } 9735 } 9736 PetscFunctionReturn(PETSC_SUCCESS); 9737 } 9738 9739 /*@ 9740 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9741 with default values. 9742 9743 Not Collective 9744 9745 Input Parameter: 9746 . info - the `MatFactorInfo` data structure 9747 9748 Level: developer 9749 9750 Notes: 9751 The solvers are generally used through the `KSP` and `PC` objects, for example 9752 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9753 9754 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9755 9756 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9757 @*/ 9758 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9759 { 9760 PetscFunctionBegin; 9761 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9762 PetscFunctionReturn(PETSC_SUCCESS); 9763 } 9764 9765 /*@ 9766 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9767 9768 Collective 9769 9770 Input Parameters: 9771 + mat - the factored matrix 9772 - is - the index set defining the Schur indices (0-based) 9773 9774 Level: advanced 9775 9776 Notes: 9777 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9778 9779 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9780 9781 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9782 9783 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9784 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9785 @*/ 9786 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9787 { 9788 PetscErrorCode (*f)(Mat, IS); 9789 9790 PetscFunctionBegin; 9791 PetscValidType(mat, 1); 9792 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9793 PetscValidType(is, 2); 9794 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9795 PetscCheckSameComm(mat, 1, is, 2); 9796 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9797 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9798 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9799 PetscCall(MatDestroy(&mat->schur)); 9800 PetscCall((*f)(mat, is)); 9801 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9802 PetscFunctionReturn(PETSC_SUCCESS); 9803 } 9804 9805 /*@ 9806 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9807 9808 Logically Collective 9809 9810 Input Parameters: 9811 + F - the factored matrix obtained by calling `MatGetFactor()` 9812 . S - location where to return the Schur complement, can be `NULL` 9813 - status - the status of the Schur complement matrix, can be `NULL` 9814 9815 Level: advanced 9816 9817 Notes: 9818 You must call `MatFactorSetSchurIS()` before calling this routine. 9819 9820 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9821 9822 The routine provides a copy of the Schur matrix stored within the solver data structures. 9823 The caller must destroy the object when it is no longer needed. 9824 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9825 9826 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) 9827 9828 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9829 9830 Developer Note: 9831 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9832 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9833 9834 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9835 @*/ 9836 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9837 { 9838 PetscFunctionBegin; 9839 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9840 if (S) PetscAssertPointer(S, 2); 9841 if (status) PetscAssertPointer(status, 3); 9842 if (S) { 9843 PetscErrorCode (*f)(Mat, Mat *); 9844 9845 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9846 if (f) { 9847 PetscCall((*f)(F, S)); 9848 } else { 9849 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9850 } 9851 } 9852 if (status) *status = F->schur_status; 9853 PetscFunctionReturn(PETSC_SUCCESS); 9854 } 9855 9856 /*@ 9857 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9858 9859 Logically Collective 9860 9861 Input Parameters: 9862 + F - the factored matrix obtained by calling `MatGetFactor()` 9863 . S - location where to return the Schur complement, can be `NULL` 9864 - status - the status of the Schur complement matrix, can be `NULL` 9865 9866 Level: advanced 9867 9868 Notes: 9869 You must call `MatFactorSetSchurIS()` before calling this routine. 9870 9871 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9872 9873 The routine returns a the Schur Complement stored within the data structures of the solver. 9874 9875 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9876 9877 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9878 9879 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9880 9881 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9882 9883 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9884 @*/ 9885 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9886 { 9887 PetscFunctionBegin; 9888 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9889 if (S) { 9890 PetscAssertPointer(S, 2); 9891 *S = F->schur; 9892 } 9893 if (status) { 9894 PetscAssertPointer(status, 3); 9895 *status = F->schur_status; 9896 } 9897 PetscFunctionReturn(PETSC_SUCCESS); 9898 } 9899 9900 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9901 { 9902 Mat S = F->schur; 9903 9904 PetscFunctionBegin; 9905 switch (F->schur_status) { 9906 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9907 case MAT_FACTOR_SCHUR_INVERTED: 9908 if (S) { 9909 S->ops->solve = NULL; 9910 S->ops->matsolve = NULL; 9911 S->ops->solvetranspose = NULL; 9912 S->ops->matsolvetranspose = NULL; 9913 S->ops->solveadd = NULL; 9914 S->ops->solvetransposeadd = NULL; 9915 S->factortype = MAT_FACTOR_NONE; 9916 PetscCall(PetscFree(S->solvertype)); 9917 } 9918 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9919 break; 9920 default: 9921 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9922 } 9923 PetscFunctionReturn(PETSC_SUCCESS); 9924 } 9925 9926 /*@ 9927 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9928 9929 Logically Collective 9930 9931 Input Parameters: 9932 + F - the factored matrix obtained by calling `MatGetFactor()` 9933 . S - location where the Schur complement is stored 9934 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9935 9936 Level: advanced 9937 9938 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9939 @*/ 9940 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9941 { 9942 PetscFunctionBegin; 9943 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9944 if (S) { 9945 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9946 *S = NULL; 9947 } 9948 F->schur_status = status; 9949 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9950 PetscFunctionReturn(PETSC_SUCCESS); 9951 } 9952 9953 /*@ 9954 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9955 9956 Logically Collective 9957 9958 Input Parameters: 9959 + F - the factored matrix obtained by calling `MatGetFactor()` 9960 . rhs - location where the right-hand side of the Schur complement system is stored 9961 - sol - location where the solution of the Schur complement system has to be returned 9962 9963 Level: advanced 9964 9965 Notes: 9966 The sizes of the vectors should match the size of the Schur complement 9967 9968 Must be called after `MatFactorSetSchurIS()` 9969 9970 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9971 @*/ 9972 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9973 { 9974 PetscFunctionBegin; 9975 PetscValidType(F, 1); 9976 PetscValidType(rhs, 2); 9977 PetscValidType(sol, 3); 9978 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9979 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9980 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9981 PetscCheckSameComm(F, 1, rhs, 2); 9982 PetscCheckSameComm(F, 1, sol, 3); 9983 PetscCall(MatFactorFactorizeSchurComplement(F)); 9984 switch (F->schur_status) { 9985 case MAT_FACTOR_SCHUR_FACTORED: 9986 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9987 break; 9988 case MAT_FACTOR_SCHUR_INVERTED: 9989 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9990 break; 9991 default: 9992 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9993 } 9994 PetscFunctionReturn(PETSC_SUCCESS); 9995 } 9996 9997 /*@ 9998 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9999 10000 Logically Collective 10001 10002 Input Parameters: 10003 + F - the factored matrix obtained by calling `MatGetFactor()` 10004 . rhs - location where the right-hand side of the Schur complement system is stored 10005 - sol - location where the solution of the Schur complement system has to be returned 10006 10007 Level: advanced 10008 10009 Notes: 10010 The sizes of the vectors should match the size of the Schur complement 10011 10012 Must be called after `MatFactorSetSchurIS()` 10013 10014 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10015 @*/ 10016 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10017 { 10018 PetscFunctionBegin; 10019 PetscValidType(F, 1); 10020 PetscValidType(rhs, 2); 10021 PetscValidType(sol, 3); 10022 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10023 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10024 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10025 PetscCheckSameComm(F, 1, rhs, 2); 10026 PetscCheckSameComm(F, 1, sol, 3); 10027 PetscCall(MatFactorFactorizeSchurComplement(F)); 10028 switch (F->schur_status) { 10029 case MAT_FACTOR_SCHUR_FACTORED: 10030 PetscCall(MatSolve(F->schur, rhs, sol)); 10031 break; 10032 case MAT_FACTOR_SCHUR_INVERTED: 10033 PetscCall(MatMult(F->schur, rhs, sol)); 10034 break; 10035 default: 10036 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10037 } 10038 PetscFunctionReturn(PETSC_SUCCESS); 10039 } 10040 10041 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10042 #if PetscDefined(HAVE_CUDA) 10043 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10044 #endif 10045 10046 /* Schur status updated in the interface */ 10047 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10048 { 10049 Mat S = F->schur; 10050 10051 PetscFunctionBegin; 10052 if (S) { 10053 PetscMPIInt size; 10054 PetscBool isdense, isdensecuda; 10055 10056 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10057 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10058 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10059 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10060 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10061 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10062 if (isdense) { 10063 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10064 } else if (isdensecuda) { 10065 #if defined(PETSC_HAVE_CUDA) 10066 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10067 #endif 10068 } 10069 // HIP?????????????? 10070 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10071 } 10072 PetscFunctionReturn(PETSC_SUCCESS); 10073 } 10074 10075 /*@ 10076 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10077 10078 Logically Collective 10079 10080 Input Parameter: 10081 . F - the factored matrix obtained by calling `MatGetFactor()` 10082 10083 Level: advanced 10084 10085 Notes: 10086 Must be called after `MatFactorSetSchurIS()`. 10087 10088 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10089 10090 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10091 @*/ 10092 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10093 { 10094 PetscFunctionBegin; 10095 PetscValidType(F, 1); 10096 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10097 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10098 PetscCall(MatFactorFactorizeSchurComplement(F)); 10099 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10100 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10101 PetscFunctionReturn(PETSC_SUCCESS); 10102 } 10103 10104 /*@ 10105 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10106 10107 Logically Collective 10108 10109 Input Parameter: 10110 . F - the factored matrix obtained by calling `MatGetFactor()` 10111 10112 Level: advanced 10113 10114 Note: 10115 Must be called after `MatFactorSetSchurIS()` 10116 10117 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10118 @*/ 10119 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10120 { 10121 MatFactorInfo info; 10122 10123 PetscFunctionBegin; 10124 PetscValidType(F, 1); 10125 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10126 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10127 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10128 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10129 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10130 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10131 } else { 10132 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10133 } 10134 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10135 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10136 PetscFunctionReturn(PETSC_SUCCESS); 10137 } 10138 10139 /*@ 10140 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10141 10142 Neighbor-wise Collective 10143 10144 Input Parameters: 10145 + A - the matrix 10146 . P - the projection matrix 10147 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10148 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10149 if the result is a dense matrix this is irrelevant 10150 10151 Output Parameter: 10152 . C - the product matrix 10153 10154 Level: intermediate 10155 10156 Notes: 10157 C will be created and must be destroyed by the user with `MatDestroy()`. 10158 10159 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10160 10161 Developer Note: 10162 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10163 10164 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10165 @*/ 10166 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10167 { 10168 PetscFunctionBegin; 10169 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10170 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10171 10172 if (scall == MAT_INITIAL_MATRIX) { 10173 PetscCall(MatProductCreate(A, P, NULL, C)); 10174 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10175 PetscCall(MatProductSetAlgorithm(*C, "default")); 10176 PetscCall(MatProductSetFill(*C, fill)); 10177 10178 (*C)->product->api_user = PETSC_TRUE; 10179 PetscCall(MatProductSetFromOptions(*C)); 10180 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); 10181 PetscCall(MatProductSymbolic(*C)); 10182 } else { /* scall == MAT_REUSE_MATRIX */ 10183 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10184 } 10185 10186 PetscCall(MatProductNumeric(*C)); 10187 (*C)->symmetric = A->symmetric; 10188 (*C)->spd = A->spd; 10189 PetscFunctionReturn(PETSC_SUCCESS); 10190 } 10191 10192 /*@ 10193 MatRARt - Creates the matrix product $C = R * A * R^T$ 10194 10195 Neighbor-wise Collective 10196 10197 Input Parameters: 10198 + A - the matrix 10199 . R - the projection matrix 10200 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10201 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10202 if the result is a dense matrix this is irrelevant 10203 10204 Output Parameter: 10205 . C - the product matrix 10206 10207 Level: intermediate 10208 10209 Notes: 10210 C will be created and must be destroyed by the user with `MatDestroy()`. 10211 10212 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10213 10214 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10215 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10216 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10217 We recommend using MatPtAP(). 10218 10219 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10220 @*/ 10221 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10222 { 10223 PetscFunctionBegin; 10224 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10225 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10226 10227 if (scall == MAT_INITIAL_MATRIX) { 10228 PetscCall(MatProductCreate(A, R, NULL, C)); 10229 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10230 PetscCall(MatProductSetAlgorithm(*C, "default")); 10231 PetscCall(MatProductSetFill(*C, fill)); 10232 10233 (*C)->product->api_user = PETSC_TRUE; 10234 PetscCall(MatProductSetFromOptions(*C)); 10235 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); 10236 PetscCall(MatProductSymbolic(*C)); 10237 } else { /* scall == MAT_REUSE_MATRIX */ 10238 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10239 } 10240 10241 PetscCall(MatProductNumeric(*C)); 10242 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10243 PetscFunctionReturn(PETSC_SUCCESS); 10244 } 10245 10246 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10247 { 10248 PetscBool flg = PETSC_TRUE; 10249 10250 PetscFunctionBegin; 10251 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10252 if (scall == MAT_INITIAL_MATRIX) { 10253 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10254 PetscCall(MatProductCreate(A, B, NULL, C)); 10255 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10256 PetscCall(MatProductSetFill(*C, fill)); 10257 } else { /* scall == MAT_REUSE_MATRIX */ 10258 Mat_Product *product = (*C)->product; 10259 10260 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10261 if (flg && product && product->type != ptype) { 10262 PetscCall(MatProductClear(*C)); 10263 product = NULL; 10264 } 10265 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10266 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10267 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10268 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10269 product = (*C)->product; 10270 product->fill = fill; 10271 product->clear = PETSC_TRUE; 10272 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10273 flg = PETSC_FALSE; 10274 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10275 } 10276 } 10277 if (flg) { 10278 (*C)->product->api_user = PETSC_TRUE; 10279 PetscCall(MatProductSetType(*C, ptype)); 10280 PetscCall(MatProductSetFromOptions(*C)); 10281 PetscCall(MatProductSymbolic(*C)); 10282 } 10283 PetscCall(MatProductNumeric(*C)); 10284 PetscFunctionReturn(PETSC_SUCCESS); 10285 } 10286 10287 /*@ 10288 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10289 10290 Neighbor-wise Collective 10291 10292 Input Parameters: 10293 + A - the left matrix 10294 . B - the right matrix 10295 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10296 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10297 if the result is a dense matrix this is irrelevant 10298 10299 Output Parameter: 10300 . C - the product matrix 10301 10302 Notes: 10303 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10304 10305 `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 10306 call to this function with `MAT_INITIAL_MATRIX`. 10307 10308 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10309 10310 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`, 10311 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10312 10313 Example of Usage: 10314 .vb 10315 MatProductCreate(A,B,NULL,&C); 10316 MatProductSetType(C,MATPRODUCT_AB); 10317 MatProductSymbolic(C); 10318 MatProductNumeric(C); // compute C=A * B 10319 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10320 MatProductNumeric(C); 10321 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10322 MatProductNumeric(C); 10323 .ve 10324 10325 Level: intermediate 10326 10327 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10328 @*/ 10329 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10330 { 10331 PetscFunctionBegin; 10332 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10333 PetscFunctionReturn(PETSC_SUCCESS); 10334 } 10335 10336 /*@ 10337 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10338 10339 Neighbor-wise Collective 10340 10341 Input Parameters: 10342 + A - the left matrix 10343 . B - the right matrix 10344 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10345 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10346 10347 Output Parameter: 10348 . C - the product matrix 10349 10350 Options Database Key: 10351 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10352 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10353 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10354 10355 Level: intermediate 10356 10357 Notes: 10358 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10359 10360 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10361 10362 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10363 actually needed. 10364 10365 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10366 and for pairs of `MATMPIDENSE` matrices. 10367 10368 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10369 10370 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10371 @*/ 10372 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10373 { 10374 PetscFunctionBegin; 10375 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10376 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10377 PetscFunctionReturn(PETSC_SUCCESS); 10378 } 10379 10380 /*@ 10381 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10382 10383 Neighbor-wise Collective 10384 10385 Input Parameters: 10386 + A - the left matrix 10387 . B - the right matrix 10388 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10389 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10390 10391 Output Parameter: 10392 . C - the product matrix 10393 10394 Level: intermediate 10395 10396 Notes: 10397 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10398 10399 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10400 10401 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10402 10403 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10404 actually needed. 10405 10406 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10407 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10408 10409 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10410 @*/ 10411 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10412 { 10413 PetscFunctionBegin; 10414 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10415 PetscFunctionReturn(PETSC_SUCCESS); 10416 } 10417 10418 /*@ 10419 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10420 10421 Neighbor-wise Collective 10422 10423 Input Parameters: 10424 + A - the left matrix 10425 . B - the middle matrix 10426 . C - the right matrix 10427 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10428 - fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate 10429 if the result is a dense matrix this is irrelevant 10430 10431 Output Parameter: 10432 . D - the product matrix 10433 10434 Level: intermediate 10435 10436 Notes: 10437 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10438 10439 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10440 10441 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10442 10443 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10444 actually needed. 10445 10446 If you have many matrices with the same non-zero structure to multiply, you 10447 should use `MAT_REUSE_MATRIX` in all calls but the first 10448 10449 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10450 @*/ 10451 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10452 { 10453 PetscFunctionBegin; 10454 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10455 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10456 10457 if (scall == MAT_INITIAL_MATRIX) { 10458 PetscCall(MatProductCreate(A, B, C, D)); 10459 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10460 PetscCall(MatProductSetAlgorithm(*D, "default")); 10461 PetscCall(MatProductSetFill(*D, fill)); 10462 10463 (*D)->product->api_user = PETSC_TRUE; 10464 PetscCall(MatProductSetFromOptions(*D)); 10465 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, 10466 ((PetscObject)C)->type_name); 10467 PetscCall(MatProductSymbolic(*D)); 10468 } else { /* user may change input matrices when REUSE */ 10469 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10470 } 10471 PetscCall(MatProductNumeric(*D)); 10472 PetscFunctionReturn(PETSC_SUCCESS); 10473 } 10474 10475 /*@ 10476 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10477 10478 Collective 10479 10480 Input Parameters: 10481 + mat - the matrix 10482 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10483 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10484 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10485 10486 Output Parameter: 10487 . matredundant - redundant matrix 10488 10489 Level: advanced 10490 10491 Notes: 10492 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10493 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10494 10495 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10496 calling it. 10497 10498 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10499 10500 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10501 @*/ 10502 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10503 { 10504 MPI_Comm comm; 10505 PetscMPIInt size; 10506 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10507 Mat_Redundant *redund = NULL; 10508 PetscSubcomm psubcomm = NULL; 10509 MPI_Comm subcomm_in = subcomm; 10510 Mat *matseq; 10511 IS isrow, iscol; 10512 PetscBool newsubcomm = PETSC_FALSE; 10513 10514 PetscFunctionBegin; 10515 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10516 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10517 PetscAssertPointer(*matredundant, 5); 10518 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10519 } 10520 10521 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10522 if (size == 1 || nsubcomm == 1) { 10523 if (reuse == MAT_INITIAL_MATRIX) { 10524 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10525 } else { 10526 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"); 10527 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10528 } 10529 PetscFunctionReturn(PETSC_SUCCESS); 10530 } 10531 10532 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10533 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10534 MatCheckPreallocated(mat, 1); 10535 10536 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10537 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10538 /* create psubcomm, then get subcomm */ 10539 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10540 PetscCallMPI(MPI_Comm_size(comm, &size)); 10541 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10542 10543 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10544 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10545 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10546 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10547 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10548 newsubcomm = PETSC_TRUE; 10549 PetscCall(PetscSubcommDestroy(&psubcomm)); 10550 } 10551 10552 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10553 if (reuse == MAT_INITIAL_MATRIX) { 10554 mloc_sub = PETSC_DECIDE; 10555 nloc_sub = PETSC_DECIDE; 10556 if (bs < 1) { 10557 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10558 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10559 } else { 10560 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10561 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10562 } 10563 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10564 rstart = rend - mloc_sub; 10565 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10566 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10567 PetscCall(ISSetIdentity(iscol)); 10568 } else { /* reuse == MAT_REUSE_MATRIX */ 10569 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"); 10570 /* retrieve subcomm */ 10571 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10572 redund = (*matredundant)->redundant; 10573 isrow = redund->isrow; 10574 iscol = redund->iscol; 10575 matseq = redund->matseq; 10576 } 10577 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10578 10579 /* get matredundant over subcomm */ 10580 if (reuse == MAT_INITIAL_MATRIX) { 10581 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10582 10583 /* create a supporting struct and attach it to C for reuse */ 10584 PetscCall(PetscNew(&redund)); 10585 (*matredundant)->redundant = redund; 10586 redund->isrow = isrow; 10587 redund->iscol = iscol; 10588 redund->matseq = matseq; 10589 if (newsubcomm) { 10590 redund->subcomm = subcomm; 10591 } else { 10592 redund->subcomm = MPI_COMM_NULL; 10593 } 10594 } else { 10595 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10596 } 10597 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10598 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10599 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10600 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10601 } 10602 #endif 10603 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10604 PetscFunctionReturn(PETSC_SUCCESS); 10605 } 10606 10607 /*@C 10608 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10609 a given `Mat`. Each submatrix can span multiple procs. 10610 10611 Collective 10612 10613 Input Parameters: 10614 + mat - the matrix 10615 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10616 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10617 10618 Output Parameter: 10619 . subMat - parallel sub-matrices each spanning a given `subcomm` 10620 10621 Level: advanced 10622 10623 Notes: 10624 The submatrix partition across processors is dictated by `subComm` a 10625 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10626 is not restricted to be grouped with consecutive original MPI processes. 10627 10628 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10629 map directly to the layout of the original matrix [wrt the local 10630 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10631 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10632 the `subMat`. However the offDiagMat looses some columns - and this is 10633 reconstructed with `MatSetValues()` 10634 10635 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10636 10637 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10638 @*/ 10639 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10640 { 10641 PetscMPIInt commsize, subCommSize; 10642 10643 PetscFunctionBegin; 10644 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10645 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10646 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10647 10648 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"); 10649 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10650 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10651 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10652 PetscFunctionReturn(PETSC_SUCCESS); 10653 } 10654 10655 /*@ 10656 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10657 10658 Not Collective 10659 10660 Input Parameters: 10661 + mat - matrix to extract local submatrix from 10662 . isrow - local row indices for submatrix 10663 - iscol - local column indices for submatrix 10664 10665 Output Parameter: 10666 . submat - the submatrix 10667 10668 Level: intermediate 10669 10670 Notes: 10671 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10672 10673 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10674 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10675 10676 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10677 `MatSetValuesBlockedLocal()` will also be implemented. 10678 10679 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10680 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10681 10682 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10683 @*/ 10684 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10685 { 10686 PetscFunctionBegin; 10687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10688 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10689 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10690 PetscCheckSameComm(isrow, 2, iscol, 3); 10691 PetscAssertPointer(submat, 4); 10692 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10693 10694 if (mat->ops->getlocalsubmatrix) { 10695 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10696 } else { 10697 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10698 } 10699 PetscFunctionReturn(PETSC_SUCCESS); 10700 } 10701 10702 /*@ 10703 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10704 10705 Not Collective 10706 10707 Input Parameters: 10708 + mat - matrix to extract local submatrix from 10709 . isrow - local row indices for submatrix 10710 . iscol - local column indices for submatrix 10711 - submat - the submatrix 10712 10713 Level: intermediate 10714 10715 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10716 @*/ 10717 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10718 { 10719 PetscFunctionBegin; 10720 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10721 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10722 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10723 PetscCheckSameComm(isrow, 2, iscol, 3); 10724 PetscAssertPointer(submat, 4); 10725 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10726 10727 if (mat->ops->restorelocalsubmatrix) { 10728 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10729 } else { 10730 PetscCall(MatDestroy(submat)); 10731 } 10732 *submat = NULL; 10733 PetscFunctionReturn(PETSC_SUCCESS); 10734 } 10735 10736 /*@ 10737 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10738 10739 Collective 10740 10741 Input Parameter: 10742 . mat - the matrix 10743 10744 Output Parameter: 10745 . is - if any rows have zero diagonals this contains the list of them 10746 10747 Level: developer 10748 10749 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10750 @*/ 10751 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10752 { 10753 PetscFunctionBegin; 10754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10755 PetscValidType(mat, 1); 10756 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10757 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10758 10759 if (!mat->ops->findzerodiagonals) { 10760 Vec diag; 10761 const PetscScalar *a; 10762 PetscInt *rows; 10763 PetscInt rStart, rEnd, r, nrow = 0; 10764 10765 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10766 PetscCall(MatGetDiagonal(mat, diag)); 10767 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10768 PetscCall(VecGetArrayRead(diag, &a)); 10769 for (r = 0; r < rEnd - rStart; ++r) 10770 if (a[r] == 0.0) ++nrow; 10771 PetscCall(PetscMalloc1(nrow, &rows)); 10772 nrow = 0; 10773 for (r = 0; r < rEnd - rStart; ++r) 10774 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10775 PetscCall(VecRestoreArrayRead(diag, &a)); 10776 PetscCall(VecDestroy(&diag)); 10777 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10778 } else { 10779 PetscUseTypeMethod(mat, findzerodiagonals, is); 10780 } 10781 PetscFunctionReturn(PETSC_SUCCESS); 10782 } 10783 10784 /*@ 10785 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10786 10787 Collective 10788 10789 Input Parameter: 10790 . mat - the matrix 10791 10792 Output Parameter: 10793 . is - contains the list of rows with off block diagonal entries 10794 10795 Level: developer 10796 10797 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10798 @*/ 10799 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10800 { 10801 PetscFunctionBegin; 10802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10803 PetscValidType(mat, 1); 10804 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10805 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10806 10807 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10808 PetscFunctionReturn(PETSC_SUCCESS); 10809 } 10810 10811 /*@C 10812 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10813 10814 Collective; No Fortran Support 10815 10816 Input Parameter: 10817 . mat - the matrix 10818 10819 Output Parameter: 10820 . values - the block inverses in column major order (FORTRAN-like) 10821 10822 Level: advanced 10823 10824 Notes: 10825 The size of the blocks is determined by the block size of the matrix. 10826 10827 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10828 10829 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10830 10831 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10832 @*/ 10833 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10834 { 10835 PetscFunctionBegin; 10836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10837 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10838 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10839 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10840 PetscFunctionReturn(PETSC_SUCCESS); 10841 } 10842 10843 /*@ 10844 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10845 10846 Collective; No Fortran Support 10847 10848 Input Parameters: 10849 + mat - the matrix 10850 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10851 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10852 10853 Output Parameter: 10854 . values - the block inverses in column major order (FORTRAN-like) 10855 10856 Level: advanced 10857 10858 Notes: 10859 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10860 10861 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10862 10863 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10864 @*/ 10865 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10866 { 10867 PetscFunctionBegin; 10868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10869 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10870 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10871 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10872 PetscFunctionReturn(PETSC_SUCCESS); 10873 } 10874 10875 /*@ 10876 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10877 10878 Collective 10879 10880 Input Parameters: 10881 + A - the matrix 10882 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10883 10884 Level: advanced 10885 10886 Note: 10887 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10888 10889 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10890 @*/ 10891 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10892 { 10893 const PetscScalar *vals; 10894 PetscInt *dnnz; 10895 PetscInt m, rstart, rend, bs, i, j; 10896 10897 PetscFunctionBegin; 10898 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10899 PetscCall(MatGetBlockSize(A, &bs)); 10900 PetscCall(MatGetLocalSize(A, &m, NULL)); 10901 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10902 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10903 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10904 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10905 PetscCall(PetscFree(dnnz)); 10906 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10907 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10908 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10909 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10910 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10911 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10912 PetscFunctionReturn(PETSC_SUCCESS); 10913 } 10914 10915 /*@ 10916 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10917 via `MatTransposeColoringCreate()`. 10918 10919 Collective 10920 10921 Input Parameter: 10922 . c - coloring context 10923 10924 Level: intermediate 10925 10926 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10927 @*/ 10928 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10929 { 10930 MatTransposeColoring matcolor = *c; 10931 10932 PetscFunctionBegin; 10933 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10934 if (--((PetscObject)matcolor)->refct > 0) { 10935 matcolor = NULL; 10936 PetscFunctionReturn(PETSC_SUCCESS); 10937 } 10938 10939 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10940 PetscCall(PetscFree(matcolor->rows)); 10941 PetscCall(PetscFree(matcolor->den2sp)); 10942 PetscCall(PetscFree(matcolor->colorforcol)); 10943 PetscCall(PetscFree(matcolor->columns)); 10944 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10945 PetscCall(PetscHeaderDestroy(c)); 10946 PetscFunctionReturn(PETSC_SUCCESS); 10947 } 10948 10949 /*@ 10950 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10951 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10952 `MatTransposeColoring` to sparse `B`. 10953 10954 Collective 10955 10956 Input Parameters: 10957 + coloring - coloring context created with `MatTransposeColoringCreate()` 10958 - B - sparse matrix 10959 10960 Output Parameter: 10961 . Btdense - dense matrix $B^T$ 10962 10963 Level: developer 10964 10965 Note: 10966 These are used internally for some implementations of `MatRARt()` 10967 10968 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10969 @*/ 10970 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10971 { 10972 PetscFunctionBegin; 10973 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10974 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10975 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10976 10977 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10978 PetscFunctionReturn(PETSC_SUCCESS); 10979 } 10980 10981 /*@ 10982 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10983 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10984 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10985 $C_{sp}$ from $C_{den}$. 10986 10987 Collective 10988 10989 Input Parameters: 10990 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10991 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10992 10993 Output Parameter: 10994 . Csp - sparse matrix 10995 10996 Level: developer 10997 10998 Note: 10999 These are used internally for some implementations of `MatRARt()` 11000 11001 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11002 @*/ 11003 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11004 { 11005 PetscFunctionBegin; 11006 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11007 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11008 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11009 11010 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11011 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11012 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11013 PetscFunctionReturn(PETSC_SUCCESS); 11014 } 11015 11016 /*@ 11017 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11018 11019 Collective 11020 11021 Input Parameters: 11022 + mat - the matrix product C 11023 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11024 11025 Output Parameter: 11026 . color - the new coloring context 11027 11028 Level: intermediate 11029 11030 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11031 `MatTransColoringApplyDenToSp()` 11032 @*/ 11033 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11034 { 11035 MatTransposeColoring c; 11036 MPI_Comm comm; 11037 11038 PetscFunctionBegin; 11039 PetscAssertPointer(color, 3); 11040 11041 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11042 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11043 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11044 c->ctype = iscoloring->ctype; 11045 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11046 *color = c; 11047 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11048 PetscFunctionReturn(PETSC_SUCCESS); 11049 } 11050 11051 /*@ 11052 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11053 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11054 11055 Not Collective 11056 11057 Input Parameter: 11058 . mat - the matrix 11059 11060 Output Parameter: 11061 . state - the current state 11062 11063 Level: intermediate 11064 11065 Notes: 11066 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11067 different matrices 11068 11069 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11070 11071 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11072 11073 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11074 @*/ 11075 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11076 { 11077 PetscFunctionBegin; 11078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11079 *state = mat->nonzerostate; 11080 PetscFunctionReturn(PETSC_SUCCESS); 11081 } 11082 11083 /*@ 11084 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11085 matrices from each processor 11086 11087 Collective 11088 11089 Input Parameters: 11090 + comm - the communicators the parallel matrix will live on 11091 . seqmat - the input sequential matrices 11092 . n - number of local columns (or `PETSC_DECIDE`) 11093 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11094 11095 Output Parameter: 11096 . mpimat - the parallel matrix generated 11097 11098 Level: developer 11099 11100 Note: 11101 The number of columns of the matrix in EACH processor MUST be the same. 11102 11103 .seealso: [](ch_matrices), `Mat` 11104 @*/ 11105 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11106 { 11107 PetscMPIInt size; 11108 11109 PetscFunctionBegin; 11110 PetscCallMPI(MPI_Comm_size(comm, &size)); 11111 if (size == 1) { 11112 if (reuse == MAT_INITIAL_MATRIX) { 11113 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11114 } else { 11115 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11116 } 11117 PetscFunctionReturn(PETSC_SUCCESS); 11118 } 11119 11120 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"); 11121 11122 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11123 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11124 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11125 PetscFunctionReturn(PETSC_SUCCESS); 11126 } 11127 11128 /*@ 11129 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11130 11131 Collective 11132 11133 Input Parameters: 11134 + A - the matrix to create subdomains from 11135 - N - requested number of subdomains 11136 11137 Output Parameters: 11138 + n - number of subdomains resulting on this MPI process 11139 - iss - `IS` list with indices of subdomains on this MPI process 11140 11141 Level: advanced 11142 11143 Note: 11144 The number of subdomains must be smaller than the communicator size 11145 11146 .seealso: [](ch_matrices), `Mat`, `IS` 11147 @*/ 11148 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11149 { 11150 MPI_Comm comm, subcomm; 11151 PetscMPIInt size, rank, color; 11152 PetscInt rstart, rend, k; 11153 11154 PetscFunctionBegin; 11155 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11156 PetscCallMPI(MPI_Comm_size(comm, &size)); 11157 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11158 PetscCheck(N >= 1 && N < (PetscInt)size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N); 11159 *n = 1; 11160 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11161 color = rank / k; 11162 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11163 PetscCall(PetscMalloc1(1, iss)); 11164 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11165 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11166 PetscCallMPI(MPI_Comm_free(&subcomm)); 11167 PetscFunctionReturn(PETSC_SUCCESS); 11168 } 11169 11170 /*@ 11171 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11172 11173 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11174 If they are not the same, uses `MatMatMatMult()`. 11175 11176 Once the coarse grid problem is constructed, correct for interpolation operators 11177 that are not of full rank, which can legitimately happen in the case of non-nested 11178 geometric multigrid. 11179 11180 Input Parameters: 11181 + restrct - restriction operator 11182 . dA - fine grid matrix 11183 . interpolate - interpolation operator 11184 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11185 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11186 11187 Output Parameter: 11188 . A - the Galerkin coarse matrix 11189 11190 Options Database Key: 11191 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11192 11193 Level: developer 11194 11195 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11196 @*/ 11197 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11198 { 11199 IS zerorows; 11200 Vec diag; 11201 11202 PetscFunctionBegin; 11203 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11204 /* Construct the coarse grid matrix */ 11205 if (interpolate == restrct) { 11206 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11207 } else { 11208 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11209 } 11210 11211 /* If the interpolation matrix is not of full rank, A will have zero rows. 11212 This can legitimately happen in the case of non-nested geometric multigrid. 11213 In that event, we set the rows of the matrix to the rows of the identity, 11214 ignoring the equations (as the RHS will also be zero). */ 11215 11216 PetscCall(MatFindZeroRows(*A, &zerorows)); 11217 11218 if (zerorows != NULL) { /* if there are any zero rows */ 11219 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11220 PetscCall(MatGetDiagonal(*A, diag)); 11221 PetscCall(VecISSet(diag, zerorows, 1.0)); 11222 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11223 PetscCall(VecDestroy(&diag)); 11224 PetscCall(ISDestroy(&zerorows)); 11225 } 11226 PetscFunctionReturn(PETSC_SUCCESS); 11227 } 11228 11229 /*@C 11230 MatSetOperation - Allows user to set a matrix operation for any matrix type 11231 11232 Logically Collective 11233 11234 Input Parameters: 11235 + mat - the matrix 11236 . op - the name of the operation 11237 - f - the function that provides the operation 11238 11239 Level: developer 11240 11241 Example Usage: 11242 .vb 11243 extern PetscErrorCode usermult(Mat, Vec, Vec); 11244 11245 PetscCall(MatCreateXXX(comm, ..., &A)); 11246 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11247 .ve 11248 11249 Notes: 11250 See the file `include/petscmat.h` for a complete list of matrix 11251 operations, which all have the form MATOP_<OPERATION>, where 11252 <OPERATION> is the name (in all capital letters) of the 11253 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11254 11255 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11256 sequence as the usual matrix interface routines, since they 11257 are intended to be accessed via the usual matrix interface 11258 routines, e.g., 11259 .vb 11260 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11261 .ve 11262 11263 In particular each function MUST return `PETSC_SUCCESS` on success and 11264 nonzero on failure. 11265 11266 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11267 11268 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11269 @*/ 11270 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11271 { 11272 PetscFunctionBegin; 11273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11274 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11275 (((void (**)(void))mat->ops)[op]) = f; 11276 PetscFunctionReturn(PETSC_SUCCESS); 11277 } 11278 11279 /*@C 11280 MatGetOperation - Gets a matrix operation for any matrix type. 11281 11282 Not Collective 11283 11284 Input Parameters: 11285 + mat - the matrix 11286 - op - the name of the operation 11287 11288 Output Parameter: 11289 . f - the function that provides the operation 11290 11291 Level: developer 11292 11293 Example Usage: 11294 .vb 11295 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11296 11297 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11298 .ve 11299 11300 Notes: 11301 See the file include/petscmat.h for a complete list of matrix 11302 operations, which all have the form MATOP_<OPERATION>, where 11303 <OPERATION> is the name (in all capital letters) of the 11304 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11305 11306 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11307 11308 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11309 @*/ 11310 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11311 { 11312 PetscFunctionBegin; 11313 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11314 *f = (((void (**)(void))mat->ops)[op]); 11315 PetscFunctionReturn(PETSC_SUCCESS); 11316 } 11317 11318 /*@ 11319 MatHasOperation - Determines whether the given matrix supports the particular operation. 11320 11321 Not Collective 11322 11323 Input Parameters: 11324 + mat - the matrix 11325 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11326 11327 Output Parameter: 11328 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11329 11330 Level: advanced 11331 11332 Note: 11333 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11334 11335 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11336 @*/ 11337 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11338 { 11339 PetscFunctionBegin; 11340 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11341 PetscAssertPointer(has, 3); 11342 if (mat->ops->hasoperation) { 11343 PetscUseTypeMethod(mat, hasoperation, op, has); 11344 } else { 11345 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11346 else { 11347 *has = PETSC_FALSE; 11348 if (op == MATOP_CREATE_SUBMATRIX) { 11349 PetscMPIInt size; 11350 11351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11352 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11353 } 11354 } 11355 } 11356 PetscFunctionReturn(PETSC_SUCCESS); 11357 } 11358 11359 /*@ 11360 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11361 11362 Collective 11363 11364 Input Parameter: 11365 . mat - the matrix 11366 11367 Output Parameter: 11368 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11369 11370 Level: beginner 11371 11372 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11373 @*/ 11374 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11375 { 11376 PetscFunctionBegin; 11377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11378 PetscValidType(mat, 1); 11379 PetscAssertPointer(cong, 2); 11380 if (!mat->rmap || !mat->cmap) { 11381 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11382 PetscFunctionReturn(PETSC_SUCCESS); 11383 } 11384 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11385 PetscCall(PetscLayoutSetUp(mat->rmap)); 11386 PetscCall(PetscLayoutSetUp(mat->cmap)); 11387 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11388 if (*cong) mat->congruentlayouts = 1; 11389 else mat->congruentlayouts = 0; 11390 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11391 PetscFunctionReturn(PETSC_SUCCESS); 11392 } 11393 11394 PetscErrorCode MatSetInf(Mat A) 11395 { 11396 PetscFunctionBegin; 11397 PetscUseTypeMethod(A, setinf); 11398 PetscFunctionReturn(PETSC_SUCCESS); 11399 } 11400 11401 /*@ 11402 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 11403 and possibly removes small values from the graph structure. 11404 11405 Collective 11406 11407 Input Parameters: 11408 + A - the matrix 11409 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11410 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11411 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11412 . num_idx - size of 'index' array 11413 - index - array of block indices to use for graph strength of connection weight 11414 11415 Output Parameter: 11416 . graph - the resulting graph 11417 11418 Level: advanced 11419 11420 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11421 @*/ 11422 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11423 { 11424 PetscFunctionBegin; 11425 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11426 PetscValidType(A, 1); 11427 PetscValidLogicalCollectiveBool(A, scale, 3); 11428 PetscAssertPointer(graph, 7); 11429 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11430 PetscFunctionReturn(PETSC_SUCCESS); 11431 } 11432 11433 /*@ 11434 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11435 meaning the same memory is used for the matrix, and no new memory is allocated. 11436 11437 Collective 11438 11439 Input Parameters: 11440 + A - the matrix 11441 - 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 11442 11443 Level: intermediate 11444 11445 Developer Note: 11446 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11447 of the arrays in the data structure are unneeded. 11448 11449 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11450 @*/ 11451 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11452 { 11453 PetscFunctionBegin; 11454 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11455 PetscUseTypeMethod(A, eliminatezeros, keep); 11456 PetscFunctionReturn(PETSC_SUCCESS); 11457 } 11458