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 integer row (input) 557 integer ncols (output) 558 integer cols(maxcols) (output) 559 double precision (or double complex) 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 Notes: 629 The calling sequence is 630 .vb 631 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 632 Mat matrix (input) 633 integer row (input) 634 integer ncols (output) 635 integer cols(maxcols) (output) 636 double precision (or double complex) values(maxcols) output 637 .ve 638 Where maxcols >= maximum nonzeros in any row of the matrix. 639 640 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 641 before another call to `MatGetRow()` can be made. 642 643 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 644 @*/ 645 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 646 { 647 PetscFunctionBegin; 648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 649 if (ncols) PetscAssertPointer(ncols, 3); 650 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 651 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 652 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 653 if (ncols) *ncols = 0; 654 if (cols) *cols = NULL; 655 if (vals) *vals = NULL; 656 PetscFunctionReturn(PETSC_SUCCESS); 657 } 658 659 /*@ 660 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 661 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 662 663 Not Collective 664 665 Input Parameter: 666 . mat - the matrix 667 668 Level: advanced 669 670 Note: 671 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. 672 673 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 674 @*/ 675 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 676 { 677 PetscFunctionBegin; 678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 679 PetscValidType(mat, 1); 680 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 681 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 682 MatCheckPreallocated(mat, 1); 683 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 684 PetscUseTypeMethod(mat, getrowuppertriangular); 685 PetscFunctionReturn(PETSC_SUCCESS); 686 } 687 688 /*@ 689 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 690 691 Not Collective 692 693 Input Parameter: 694 . mat - the matrix 695 696 Level: advanced 697 698 Note: 699 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 700 701 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 702 @*/ 703 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 704 { 705 PetscFunctionBegin; 706 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 707 PetscValidType(mat, 1); 708 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 709 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 710 MatCheckPreallocated(mat, 1); 711 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 712 PetscUseTypeMethod(mat, restorerowuppertriangular); 713 PetscFunctionReturn(PETSC_SUCCESS); 714 } 715 716 /*@ 717 MatSetOptionsPrefix - Sets the prefix used for searching for all 718 `Mat` options in the database. 719 720 Logically Collective 721 722 Input Parameters: 723 + A - the matrix 724 - prefix - the prefix to prepend to all option names 725 726 Level: advanced 727 728 Notes: 729 A hyphen (-) must NOT be given at the beginning of the prefix name. 730 The first character of all runtime options is AUTOMATICALLY the hyphen. 731 732 This is NOT used for options for the factorization of the matrix. Normally the 733 prefix is automatically passed in from the PC calling the factorization. To set 734 it directly use `MatSetOptionsPrefixFactor()` 735 736 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 737 @*/ 738 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 739 { 740 PetscFunctionBegin; 741 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 742 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 743 PetscFunctionReturn(PETSC_SUCCESS); 744 } 745 746 /*@ 747 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 748 for matrices created with `MatGetFactor()` 749 750 Logically Collective 751 752 Input Parameters: 753 + A - the matrix 754 - prefix - the prefix to prepend to all option names for the factored matrix 755 756 Level: developer 757 758 Notes: 759 A hyphen (-) must NOT be given at the beginning of the prefix name. 760 The first character of all runtime options is AUTOMATICALLY the hyphen. 761 762 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 763 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 764 765 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 766 @*/ 767 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 768 { 769 PetscFunctionBegin; 770 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 771 if (prefix) { 772 PetscAssertPointer(prefix, 2); 773 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 774 if (prefix != A->factorprefix) { 775 PetscCall(PetscFree(A->factorprefix)); 776 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 777 } 778 } else PetscCall(PetscFree(A->factorprefix)); 779 PetscFunctionReturn(PETSC_SUCCESS); 780 } 781 782 /*@ 783 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 784 for matrices created with `MatGetFactor()` 785 786 Logically Collective 787 788 Input Parameters: 789 + A - the matrix 790 - prefix - the prefix to prepend to all option names for the factored matrix 791 792 Level: developer 793 794 Notes: 795 A hyphen (-) must NOT be given at the beginning of the prefix name. 796 The first character of all runtime options is AUTOMATICALLY the hyphen. 797 798 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 799 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 800 801 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 802 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 803 `MatSetOptionsPrefix()` 804 @*/ 805 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 806 { 807 size_t len1, len2, new_len; 808 809 PetscFunctionBegin; 810 PetscValidHeader(A, 1); 811 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 812 if (!A->factorprefix) { 813 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 814 PetscFunctionReturn(PETSC_SUCCESS); 815 } 816 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 817 818 PetscCall(PetscStrlen(A->factorprefix, &len1)); 819 PetscCall(PetscStrlen(prefix, &len2)); 820 new_len = len1 + len2 + 1; 821 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 822 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 823 PetscFunctionReturn(PETSC_SUCCESS); 824 } 825 826 /*@ 827 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 828 matrix options in the database. 829 830 Logically Collective 831 832 Input Parameters: 833 + A - the matrix 834 - prefix - the prefix to prepend to all option names 835 836 Level: advanced 837 838 Note: 839 A hyphen (-) must NOT be given at the beginning of the prefix name. 840 The first character of all runtime options is AUTOMATICALLY the hyphen. 841 842 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 843 @*/ 844 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 845 { 846 PetscFunctionBegin; 847 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 848 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 849 PetscFunctionReturn(PETSC_SUCCESS); 850 } 851 852 /*@ 853 MatGetOptionsPrefix - Gets the prefix used for searching for all 854 matrix options in the database. 855 856 Not Collective 857 858 Input Parameter: 859 . A - the matrix 860 861 Output Parameter: 862 . prefix - pointer to the prefix string used 863 864 Level: advanced 865 866 Fortran Note: 867 The user should pass in a string `prefix` of 868 sufficient length to hold the prefix. 869 870 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 871 @*/ 872 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 873 { 874 PetscFunctionBegin; 875 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 876 PetscAssertPointer(prefix, 2); 877 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 878 PetscFunctionReturn(PETSC_SUCCESS); 879 } 880 881 /*@C 882 MatGetState - Gets the state of a `Mat`. 883 884 Not Collective 885 886 Input Parameter: 887 . A - the matrix 888 889 Output Parameter: 890 . state - the object state 891 892 Level: advanced 893 894 Note: 895 Object state is an integer which gets increased every time 896 the object is changed. By saving and later querying the object state 897 one can determine whether information about the object is still current. 898 899 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()` 900 @*/ 901 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 902 { 903 PetscFunctionBegin; 904 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 905 PetscAssertPointer(state, 2); 906 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 907 PetscFunctionReturn(PETSC_SUCCESS); 908 } 909 910 /*@ 911 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 912 913 Collective 914 915 Input Parameter: 916 . A - the matrix 917 918 Level: beginner 919 920 Notes: 921 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 922 923 Users can reset the preallocation to access the original memory. 924 925 Currently only supported for `MATAIJ` matrices. 926 927 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 928 @*/ 929 PetscErrorCode MatResetPreallocation(Mat A) 930 { 931 PetscFunctionBegin; 932 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 933 PetscValidType(A, 1); 934 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()"); 935 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 936 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 937 PetscFunctionReturn(PETSC_SUCCESS); 938 } 939 940 /*@ 941 MatSetUp - Sets up the internal matrix data structures for later use. 942 943 Collective 944 945 Input Parameter: 946 . A - the matrix 947 948 Level: intermediate 949 950 Notes: 951 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 952 setting values in the matrix. 953 954 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 955 956 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 957 @*/ 958 PetscErrorCode MatSetUp(Mat A) 959 { 960 PetscFunctionBegin; 961 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 962 if (!((PetscObject)A)->type_name) { 963 PetscMPIInt size; 964 965 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 966 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 967 } 968 if (!A->preallocated) PetscTryTypeMethod(A, setup); 969 PetscCall(PetscLayoutSetUp(A->rmap)); 970 PetscCall(PetscLayoutSetUp(A->cmap)); 971 A->preallocated = PETSC_TRUE; 972 PetscFunctionReturn(PETSC_SUCCESS); 973 } 974 975 #if defined(PETSC_HAVE_SAWS) 976 #include <petscviewersaws.h> 977 #endif 978 979 /* 980 If threadsafety is on extraneous matrices may be printed 981 982 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 983 */ 984 #if !defined(PETSC_HAVE_THREADSAFETY) 985 static PetscInt insidematview = 0; 986 #endif 987 988 /*@ 989 MatViewFromOptions - View properties of the matrix based on options set in the options database 990 991 Collective 992 993 Input Parameters: 994 + A - the matrix 995 . obj - optional additional object that provides the options prefix to use 996 - name - command line option 997 998 Options Database Key: 999 . -mat_view [viewertype]:... - the viewer and its options 1000 1001 Level: intermediate 1002 1003 Note: 1004 .vb 1005 If no value is provided ascii:stdout is used 1006 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1007 for example ascii::ascii_info prints just the information about the object not all details 1008 unless :append is given filename opens in write mode, overwriting what was already there 1009 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1010 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1011 socket[:port] defaults to the standard output port 1012 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1013 .ve 1014 1015 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1016 @*/ 1017 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1018 { 1019 PetscFunctionBegin; 1020 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1021 #if !defined(PETSC_HAVE_THREADSAFETY) 1022 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1023 #endif 1024 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1025 PetscFunctionReturn(PETSC_SUCCESS); 1026 } 1027 1028 /*@ 1029 MatView - display information about a matrix in a variety ways 1030 1031 Collective on viewer 1032 1033 Input Parameters: 1034 + mat - the matrix 1035 - viewer - visualization context 1036 1037 Options Database Keys: 1038 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1039 . -mat_view ::ascii_info_detail - Prints more detailed info 1040 . -mat_view - Prints matrix in ASCII format 1041 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1042 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1043 . -display <name> - Sets display name (default is host) 1044 . -draw_pause <sec> - Sets number of seconds to pause after display 1045 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1046 . -viewer_socket_machine <machine> - - 1047 . -viewer_socket_port <port> - - 1048 . -mat_view binary - save matrix to file in binary format 1049 - -viewer_binary_filename <name> - - 1050 1051 Level: beginner 1052 1053 Notes: 1054 The available visualization contexts include 1055 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1056 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1057 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1058 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1059 1060 The user can open alternative visualization contexts with 1061 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1062 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1063 specified file; corresponding input uses `MatLoad()` 1064 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1065 an X window display 1066 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1067 Currently only the `MATSEQDENSE` and `MATAIJ` 1068 matrix types support the Socket viewer. 1069 1070 The user can call `PetscViewerPushFormat()` to specify the output 1071 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1072 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1073 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1074 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1075 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1076 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1077 format common among all matrix types 1078 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1079 format (which is in many cases the same as the default) 1080 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1081 size and structure (not the matrix entries) 1082 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1083 the matrix structure 1084 1085 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1086 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1087 1088 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1089 1090 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1091 viewer is used. 1092 1093 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1094 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1095 1096 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1097 and then use the following mouse functions. 1098 .vb 1099 left mouse: zoom in 1100 middle mouse: zoom out 1101 right mouse: continue with the simulation 1102 .ve 1103 1104 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1105 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1106 @*/ 1107 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1108 { 1109 PetscInt rows, cols, rbs, cbs; 1110 PetscBool isascii, isstring, issaws; 1111 PetscViewerFormat format; 1112 PetscMPIInt size; 1113 1114 PetscFunctionBegin; 1115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1116 PetscValidType(mat, 1); 1117 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1118 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1119 1120 PetscCall(PetscViewerGetFormat(viewer, &format)); 1121 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1122 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1123 1124 #if !defined(PETSC_HAVE_THREADSAFETY) 1125 insidematview++; 1126 #endif 1127 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1128 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1129 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1130 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"); 1131 1132 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1133 if (isascii) { 1134 if (!mat->preallocated) { 1135 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1136 #if !defined(PETSC_HAVE_THREADSAFETY) 1137 insidematview--; 1138 #endif 1139 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1140 PetscFunctionReturn(PETSC_SUCCESS); 1141 } 1142 if (!mat->assembled) { 1143 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1144 #if !defined(PETSC_HAVE_THREADSAFETY) 1145 insidematview--; 1146 #endif 1147 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1148 PetscFunctionReturn(PETSC_SUCCESS); 1149 } 1150 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1151 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1152 MatNullSpace nullsp, transnullsp; 1153 1154 PetscCall(PetscViewerASCIIPushTab(viewer)); 1155 PetscCall(MatGetSize(mat, &rows, &cols)); 1156 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1157 if (rbs != 1 || cbs != 1) { 1158 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" : "")); 1159 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1160 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1161 if (mat->factortype) { 1162 MatSolverType solver; 1163 PetscCall(MatFactorGetSolverType(mat, &solver)); 1164 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1165 } 1166 if (mat->ops->getinfo) { 1167 MatInfo info; 1168 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1169 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1170 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1171 } 1172 PetscCall(MatGetNullSpace(mat, &nullsp)); 1173 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1174 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1175 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1176 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1177 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1178 PetscCall(PetscViewerASCIIPushTab(viewer)); 1179 PetscCall(MatProductView(mat, viewer)); 1180 PetscCall(PetscViewerASCIIPopTab(viewer)); 1181 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1182 IS tmp; 1183 1184 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1185 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1186 PetscCall(PetscViewerASCIIPushTab(viewer)); 1187 PetscCall(ISView(tmp, viewer)); 1188 PetscCall(PetscViewerASCIIPopTab(viewer)); 1189 PetscCall(ISDestroy(&tmp)); 1190 } 1191 } 1192 } else if (issaws) { 1193 #if defined(PETSC_HAVE_SAWS) 1194 PetscMPIInt rank; 1195 1196 PetscCall(PetscObjectName((PetscObject)mat)); 1197 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1198 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1199 #endif 1200 } else if (isstring) { 1201 const char *type; 1202 PetscCall(MatGetType(mat, &type)); 1203 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1204 PetscTryTypeMethod(mat, view, viewer); 1205 } 1206 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1207 PetscCall(PetscViewerASCIIPushTab(viewer)); 1208 PetscUseTypeMethod(mat, viewnative, viewer); 1209 PetscCall(PetscViewerASCIIPopTab(viewer)); 1210 } else if (mat->ops->view) { 1211 PetscCall(PetscViewerASCIIPushTab(viewer)); 1212 PetscUseTypeMethod(mat, view, viewer); 1213 PetscCall(PetscViewerASCIIPopTab(viewer)); 1214 } 1215 if (isascii) { 1216 PetscCall(PetscViewerGetFormat(viewer, &format)); 1217 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1218 } 1219 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1220 #if !defined(PETSC_HAVE_THREADSAFETY) 1221 insidematview--; 1222 #endif 1223 PetscFunctionReturn(PETSC_SUCCESS); 1224 } 1225 1226 #if defined(PETSC_USE_DEBUG) 1227 #include <../src/sys/totalview/tv_data_display.h> 1228 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1229 { 1230 TV_add_row("Local rows", "int", &mat->rmap->n); 1231 TV_add_row("Local columns", "int", &mat->cmap->n); 1232 TV_add_row("Global rows", "int", &mat->rmap->N); 1233 TV_add_row("Global columns", "int", &mat->cmap->N); 1234 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1235 return TV_format_OK; 1236 } 1237 #endif 1238 1239 /*@ 1240 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1241 with `MatView()`. The matrix format is determined from the options database. 1242 Generates a parallel MPI matrix if the communicator has more than one 1243 processor. The default matrix type is `MATAIJ`. 1244 1245 Collective 1246 1247 Input Parameters: 1248 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1249 or some related function before a call to `MatLoad()` 1250 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1251 1252 Options Database Key: 1253 . -matload_block_size <bs> - set block size 1254 1255 Level: beginner 1256 1257 Notes: 1258 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1259 `Mat` before calling this routine if you wish to set it from the options database. 1260 1261 `MatLoad()` automatically loads into the options database any options 1262 given in the file filename.info where filename is the name of the file 1263 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1264 file will be ignored if you use the -viewer_binary_skip_info option. 1265 1266 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1267 sets the default matrix type AIJ and sets the local and global sizes. 1268 If type and/or size is already set, then the same are used. 1269 1270 In parallel, each processor can load a subset of rows (or the 1271 entire matrix). This routine is especially useful when a large 1272 matrix is stored on disk and only part of it is desired on each 1273 processor. For example, a parallel solver may access only some of 1274 the rows from each processor. The algorithm used here reads 1275 relatively small blocks of data rather than reading the entire 1276 matrix and then subsetting it. 1277 1278 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1279 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1280 or the sequence like 1281 .vb 1282 `PetscViewer` v; 1283 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1284 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1285 `PetscViewerSetFromOptions`(v); 1286 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1287 `PetscViewerFileSetName`(v,"datafile"); 1288 .ve 1289 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1290 $ -viewer_type {binary, hdf5} 1291 1292 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1293 and src/mat/tutorials/ex10.c with the second approach. 1294 1295 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1296 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1297 Multiple objects, both matrices and vectors, can be stored within the same file. 1298 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1299 1300 Most users should not need to know the details of the binary storage 1301 format, since `MatLoad()` and `MatView()` completely hide these details. 1302 But for anyone who is interested, the standard binary matrix storage 1303 format is 1304 1305 .vb 1306 PetscInt MAT_FILE_CLASSID 1307 PetscInt number of rows 1308 PetscInt number of columns 1309 PetscInt total number of nonzeros 1310 PetscInt *number nonzeros in each row 1311 PetscInt *column indices of all nonzeros (starting index is zero) 1312 PetscScalar *values of all nonzeros 1313 .ve 1314 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1315 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 1316 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1317 1318 PETSc automatically does the byte swapping for 1319 machines that store the bytes reversed. Thus if you write your own binary 1320 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1321 and `PetscBinaryWrite()` to see how this may be done. 1322 1323 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1324 Each processor's chunk is loaded independently by its owning MPI process. 1325 Multiple objects, both matrices and vectors, can be stored within the same file. 1326 They are looked up by their PetscObject name. 1327 1328 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1329 by default the same structure and naming of the AIJ arrays and column count 1330 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1331 $ save example.mat A b -v7.3 1332 can be directly read by this routine (see Reference 1 for details). 1333 1334 Depending on your MATLAB version, this format might be a default, 1335 otherwise you can set it as default in Preferences. 1336 1337 Unless -nocompression flag is used to save the file in MATLAB, 1338 PETSc must be configured with ZLIB package. 1339 1340 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1341 1342 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1343 1344 Corresponding `MatView()` is not yet implemented. 1345 1346 The loaded matrix is actually a transpose of the original one in MATLAB, 1347 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1348 With this format, matrix is automatically transposed by PETSc, 1349 unless the matrix is marked as SPD or symmetric 1350 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1351 1352 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1353 1354 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1355 @*/ 1356 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1357 { 1358 PetscBool flg; 1359 1360 PetscFunctionBegin; 1361 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1362 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1363 1364 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1365 1366 flg = PETSC_FALSE; 1367 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1368 if (flg) { 1369 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1370 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1371 } 1372 flg = PETSC_FALSE; 1373 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1374 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1375 1376 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1377 PetscUseTypeMethod(mat, load, viewer); 1378 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1379 PetscFunctionReturn(PETSC_SUCCESS); 1380 } 1381 1382 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1383 { 1384 Mat_Redundant *redund = *redundant; 1385 1386 PetscFunctionBegin; 1387 if (redund) { 1388 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1389 PetscCall(ISDestroy(&redund->isrow)); 1390 PetscCall(ISDestroy(&redund->iscol)); 1391 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1392 } else { 1393 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1394 PetscCall(PetscFree(redund->sbuf_j)); 1395 PetscCall(PetscFree(redund->sbuf_a)); 1396 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1397 PetscCall(PetscFree(redund->rbuf_j[i])); 1398 PetscCall(PetscFree(redund->rbuf_a[i])); 1399 } 1400 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1401 } 1402 1403 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1404 PetscCall(PetscFree(redund)); 1405 } 1406 PetscFunctionReturn(PETSC_SUCCESS); 1407 } 1408 1409 /*@ 1410 MatDestroy - Frees space taken by a matrix. 1411 1412 Collective 1413 1414 Input Parameter: 1415 . A - the matrix 1416 1417 Level: beginner 1418 1419 Developer Note: 1420 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1421 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1422 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1423 if changes are needed here. 1424 1425 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1426 @*/ 1427 PetscErrorCode MatDestroy(Mat *A) 1428 { 1429 PetscFunctionBegin; 1430 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1431 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1432 if (--((PetscObject)*A)->refct > 0) { 1433 *A = NULL; 1434 PetscFunctionReturn(PETSC_SUCCESS); 1435 } 1436 1437 /* if memory was published with SAWs then destroy it */ 1438 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1439 PetscTryTypeMethod(*A, destroy); 1440 1441 PetscCall(PetscFree((*A)->factorprefix)); 1442 PetscCall(PetscFree((*A)->defaultvectype)); 1443 PetscCall(PetscFree((*A)->defaultrandtype)); 1444 PetscCall(PetscFree((*A)->bsizes)); 1445 PetscCall(PetscFree((*A)->solvertype)); 1446 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1447 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1448 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1449 PetscCall(MatProductClear(*A)); 1450 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1451 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1452 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1453 PetscCall(MatDestroy(&(*A)->schur)); 1454 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1455 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1456 PetscCall(PetscHeaderDestroy(A)); 1457 PetscFunctionReturn(PETSC_SUCCESS); 1458 } 1459 1460 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1461 /*@C 1462 MatSetValues - Inserts or adds a block of values into a matrix. 1463 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1464 MUST be called after all calls to `MatSetValues()` have been completed. 1465 1466 Not Collective 1467 1468 Input Parameters: 1469 + mat - the matrix 1470 . v - a logically two-dimensional array of values 1471 . m - the number of rows 1472 . idxm - the global indices of the rows 1473 . n - the number of columns 1474 . idxn - the global indices of the columns 1475 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1476 1477 Level: beginner 1478 1479 Notes: 1480 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1481 1482 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1483 options cannot be mixed without intervening calls to the assembly 1484 routines. 1485 1486 `MatSetValues()` uses 0-based row and column numbers in Fortran 1487 as well as in C. 1488 1489 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1490 simply ignored. This allows easily inserting element stiffness matrices 1491 with homogeneous Dirichlet boundary conditions that you don't want represented 1492 in the matrix. 1493 1494 Efficiency Alert: 1495 The routine `MatSetValuesBlocked()` may offer much better efficiency 1496 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1497 1498 Developer Note: 1499 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1500 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1501 1502 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1503 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1504 @*/ 1505 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1506 { 1507 PetscFunctionBeginHot; 1508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1509 PetscValidType(mat, 1); 1510 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1511 PetscAssertPointer(idxm, 3); 1512 PetscAssertPointer(idxn, 5); 1513 MatCheckPreallocated(mat, 1); 1514 1515 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1516 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1517 1518 if (PetscDefined(USE_DEBUG)) { 1519 PetscInt i, j; 1520 1521 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1522 if (v) { 1523 for (i = 0; i < m; i++) { 1524 for (j = 0; j < n; j++) { 1525 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1526 #if defined(PETSC_USE_COMPLEX) 1527 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]); 1528 #else 1529 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]); 1530 #endif 1531 } 1532 } 1533 } 1534 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); 1535 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); 1536 } 1537 1538 if (mat->assembled) { 1539 mat->was_assembled = PETSC_TRUE; 1540 mat->assembled = PETSC_FALSE; 1541 } 1542 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1543 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1544 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1545 PetscFunctionReturn(PETSC_SUCCESS); 1546 } 1547 1548 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1549 /*@ 1550 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1551 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1552 MUST be called after all calls to `MatSetValues()` have been completed. 1553 1554 Not Collective 1555 1556 Input Parameters: 1557 + mat - the matrix 1558 . v - a logically two-dimensional array of values 1559 . ism - the rows to provide 1560 . isn - the columns to provide 1561 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1562 1563 Level: beginner 1564 1565 Notes: 1566 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1567 1568 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1569 options cannot be mixed without intervening calls to the assembly 1570 routines. 1571 1572 `MatSetValues()` uses 0-based row and column numbers in Fortran 1573 as well as in C. 1574 1575 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1576 simply ignored. This allows easily inserting element stiffness matrices 1577 with homogeneous Dirichlet boundary conditions that you don't want represented 1578 in the matrix. 1579 1580 Efficiency Alert: 1581 The routine `MatSetValuesBlocked()` may offer much better efficiency 1582 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1583 1584 This is currently not optimized for any particular `ISType` 1585 1586 Developer Note: 1587 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1588 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1589 1590 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1591 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1592 @*/ 1593 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1594 { 1595 PetscInt m, n; 1596 const PetscInt *rows, *cols; 1597 1598 PetscFunctionBeginHot; 1599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1600 PetscCall(ISGetIndices(ism, &rows)); 1601 PetscCall(ISGetIndices(isn, &cols)); 1602 PetscCall(ISGetLocalSize(ism, &m)); 1603 PetscCall(ISGetLocalSize(isn, &n)); 1604 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1605 PetscCall(ISRestoreIndices(ism, &rows)); 1606 PetscCall(ISRestoreIndices(isn, &cols)); 1607 PetscFunctionReturn(PETSC_SUCCESS); 1608 } 1609 1610 /*@ 1611 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1612 values into a matrix 1613 1614 Not Collective 1615 1616 Input Parameters: 1617 + mat - the matrix 1618 . row - the (block) row to set 1619 - v - a logically two-dimensional array of values 1620 1621 Level: intermediate 1622 1623 Notes: 1624 The values, `v`, are column-oriented (for the block version) and sorted 1625 1626 All the nonzero values in `row` must be provided 1627 1628 The matrix must have previously had its column indices set, likely by having been assembled. 1629 1630 `row` must belong to this MPI process 1631 1632 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1633 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1634 @*/ 1635 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1636 { 1637 PetscInt globalrow; 1638 1639 PetscFunctionBegin; 1640 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1641 PetscValidType(mat, 1); 1642 PetscAssertPointer(v, 3); 1643 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1644 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1645 PetscFunctionReturn(PETSC_SUCCESS); 1646 } 1647 1648 /*@ 1649 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1650 values into a matrix 1651 1652 Not Collective 1653 1654 Input Parameters: 1655 + mat - the matrix 1656 . row - the (block) row to set 1657 - 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 1658 1659 Level: advanced 1660 1661 Notes: 1662 The values, `v`, are column-oriented for the block version. 1663 1664 All the nonzeros in `row` must be provided 1665 1666 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1667 1668 `row` must belong to this process 1669 1670 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1671 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1672 @*/ 1673 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1674 { 1675 PetscFunctionBeginHot; 1676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1677 PetscValidType(mat, 1); 1678 MatCheckPreallocated(mat, 1); 1679 PetscAssertPointer(v, 3); 1680 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1681 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1682 mat->insertmode = INSERT_VALUES; 1683 1684 if (mat->assembled) { 1685 mat->was_assembled = PETSC_TRUE; 1686 mat->assembled = PETSC_FALSE; 1687 } 1688 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1689 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1690 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1691 PetscFunctionReturn(PETSC_SUCCESS); 1692 } 1693 1694 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1695 /*@ 1696 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1697 Using structured grid indexing 1698 1699 Not Collective 1700 1701 Input Parameters: 1702 + mat - the matrix 1703 . m - number of rows being entered 1704 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1705 . n - number of columns being entered 1706 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1707 . v - a logically two-dimensional array of values 1708 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1709 1710 Level: beginner 1711 1712 Notes: 1713 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1714 1715 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1716 options cannot be mixed without intervening calls to the assembly 1717 routines. 1718 1719 The grid coordinates are across the entire grid, not just the local portion 1720 1721 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1722 as well as in C. 1723 1724 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1725 1726 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1727 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1728 1729 The columns and rows in the stencil passed in MUST be contained within the 1730 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1731 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1732 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1733 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1734 1735 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1736 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1737 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1738 `DM_BOUNDARY_PERIODIC` boundary type. 1739 1740 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 1741 a single value per point) you can skip filling those indices. 1742 1743 Inspired by the structured grid interface to the HYPRE package 1744 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1745 1746 Efficiency Alert: 1747 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1748 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1749 1750 Fortran Note: 1751 `idxm` and `idxn` should be declared as 1752 $ MatStencil idxm(4,m),idxn(4,n) 1753 and the values inserted using 1754 .vb 1755 idxm(MatStencil_i,1) = i 1756 idxm(MatStencil_j,1) = j 1757 idxm(MatStencil_k,1) = k 1758 idxm(MatStencil_c,1) = c 1759 etc 1760 .ve 1761 1762 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1763 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1764 @*/ 1765 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1766 { 1767 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1768 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1769 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1770 1771 PetscFunctionBegin; 1772 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1774 PetscValidType(mat, 1); 1775 PetscAssertPointer(idxm, 3); 1776 PetscAssertPointer(idxn, 5); 1777 1778 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1779 jdxm = buf; 1780 jdxn = buf + m; 1781 } else { 1782 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1783 jdxm = bufm; 1784 jdxn = bufn; 1785 } 1786 for (i = 0; i < m; i++) { 1787 for (j = 0; j < 3 - sdim; j++) dxm++; 1788 tmp = *dxm++ - starts[0]; 1789 for (j = 0; j < dim - 1; j++) { 1790 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1791 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1792 } 1793 if (mat->stencil.noc) dxm++; 1794 jdxm[i] = tmp; 1795 } 1796 for (i = 0; i < n; i++) { 1797 for (j = 0; j < 3 - sdim; j++) dxn++; 1798 tmp = *dxn++ - starts[0]; 1799 for (j = 0; j < dim - 1; j++) { 1800 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1801 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1802 } 1803 if (mat->stencil.noc) dxn++; 1804 jdxn[i] = tmp; 1805 } 1806 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1807 PetscCall(PetscFree2(bufm, bufn)); 1808 PetscFunctionReturn(PETSC_SUCCESS); 1809 } 1810 1811 /*@ 1812 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1813 Using structured grid indexing 1814 1815 Not Collective 1816 1817 Input Parameters: 1818 + mat - the matrix 1819 . m - number of rows being entered 1820 . idxm - grid coordinates for matrix rows being entered 1821 . n - number of columns being entered 1822 . idxn - grid coordinates for matrix columns being entered 1823 . v - a logically two-dimensional array of values 1824 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1825 1826 Level: beginner 1827 1828 Notes: 1829 By default the values, `v`, are row-oriented and unsorted. 1830 See `MatSetOption()` for other options. 1831 1832 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1833 options cannot be mixed without intervening calls to the assembly 1834 routines. 1835 1836 The grid coordinates are across the entire grid, not just the local portion 1837 1838 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1839 as well as in C. 1840 1841 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1842 1843 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1844 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1845 1846 The columns and rows in the stencil passed in MUST be contained within the 1847 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1848 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1849 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1850 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1851 1852 Negative indices may be passed in idxm and idxn, these rows and columns are 1853 simply ignored. This allows easily inserting element stiffness matrices 1854 with homogeneous Dirichlet boundary conditions that you don't want represented 1855 in the matrix. 1856 1857 Inspired by the structured grid interface to the HYPRE package 1858 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1859 1860 Fortran Note: 1861 `idxm` and `idxn` should be declared as 1862 $ MatStencil idxm(4,m),idxn(4,n) 1863 and the values inserted using 1864 .vb 1865 idxm(MatStencil_i,1) = i 1866 idxm(MatStencil_j,1) = j 1867 idxm(MatStencil_k,1) = k 1868 etc 1869 .ve 1870 1871 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1872 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1873 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1874 @*/ 1875 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1876 { 1877 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1878 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1879 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1880 1881 PetscFunctionBegin; 1882 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1884 PetscValidType(mat, 1); 1885 PetscAssertPointer(idxm, 3); 1886 PetscAssertPointer(idxn, 5); 1887 PetscAssertPointer(v, 6); 1888 1889 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1890 jdxm = buf; 1891 jdxn = buf + m; 1892 } else { 1893 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1894 jdxm = bufm; 1895 jdxn = bufn; 1896 } 1897 for (i = 0; i < m; i++) { 1898 for (j = 0; j < 3 - sdim; j++) dxm++; 1899 tmp = *dxm++ - starts[0]; 1900 for (j = 0; j < sdim - 1; j++) { 1901 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1902 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1903 } 1904 dxm++; 1905 jdxm[i] = tmp; 1906 } 1907 for (i = 0; i < n; i++) { 1908 for (j = 0; j < 3 - sdim; j++) dxn++; 1909 tmp = *dxn++ - starts[0]; 1910 for (j = 0; j < sdim - 1; j++) { 1911 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1912 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1913 } 1914 dxn++; 1915 jdxn[i] = tmp; 1916 } 1917 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1918 PetscCall(PetscFree2(bufm, bufn)); 1919 PetscFunctionReturn(PETSC_SUCCESS); 1920 } 1921 1922 /*@ 1923 MatSetStencil - Sets the grid information for setting values into a matrix via 1924 `MatSetValuesStencil()` 1925 1926 Not Collective 1927 1928 Input Parameters: 1929 + mat - the matrix 1930 . dim - dimension of the grid 1, 2, or 3 1931 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1932 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1933 - dof - number of degrees of freedom per node 1934 1935 Level: beginner 1936 1937 Notes: 1938 Inspired by the structured grid interface to the HYPRE package 1939 (www.llnl.gov/CASC/hyper) 1940 1941 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1942 user. 1943 1944 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1945 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1946 @*/ 1947 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1948 { 1949 PetscFunctionBegin; 1950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1951 PetscAssertPointer(dims, 3); 1952 PetscAssertPointer(starts, 4); 1953 1954 mat->stencil.dim = dim + (dof > 1); 1955 for (PetscInt i = 0; i < dim; i++) { 1956 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1957 mat->stencil.starts[i] = starts[dim - i - 1]; 1958 } 1959 mat->stencil.dims[dim] = dof; 1960 mat->stencil.starts[dim] = 0; 1961 mat->stencil.noc = (PetscBool)(dof == 1); 1962 PetscFunctionReturn(PETSC_SUCCESS); 1963 } 1964 1965 /*@C 1966 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1967 1968 Not Collective 1969 1970 Input Parameters: 1971 + mat - the matrix 1972 . v - a logically two-dimensional array of values 1973 . m - the number of block rows 1974 . idxm - the global block indices 1975 . n - the number of block columns 1976 . idxn - the global block indices 1977 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1978 1979 Level: intermediate 1980 1981 Notes: 1982 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1983 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1984 1985 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1986 NOT the total number of rows/columns; for example, if the block size is 2 and 1987 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1988 The values in `idxm` would be 1 2; that is the first index for each block divided by 1989 the block size. 1990 1991 You must call `MatSetBlockSize()` when constructing this matrix (before 1992 preallocating it). 1993 1994 By default the values, `v`, are row-oriented, so the layout of 1995 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1996 1997 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1998 options cannot be mixed without intervening calls to the assembly 1999 routines. 2000 2001 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2002 as well as in C. 2003 2004 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2005 simply ignored. This allows easily inserting element stiffness matrices 2006 with homogeneous Dirichlet boundary conditions that you don't want represented 2007 in the matrix. 2008 2009 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2010 internal searching must be done to determine where to place the 2011 data in the matrix storage space. By instead inserting blocks of 2012 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2013 reduced. 2014 2015 Example: 2016 .vb 2017 Suppose m=n=2 and block size(bs) = 2 The array is 2018 2019 1 2 | 3 4 2020 5 6 | 7 8 2021 - - - | - - - 2022 9 10 | 11 12 2023 13 14 | 15 16 2024 2025 v[] should be passed in like 2026 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2027 2028 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2029 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2030 .ve 2031 2032 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2033 @*/ 2034 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2035 { 2036 PetscFunctionBeginHot; 2037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2038 PetscValidType(mat, 1); 2039 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2040 PetscAssertPointer(idxm, 3); 2041 PetscAssertPointer(idxn, 5); 2042 MatCheckPreallocated(mat, 1); 2043 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2044 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2045 if (PetscDefined(USE_DEBUG)) { 2046 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2047 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2048 } 2049 if (PetscDefined(USE_DEBUG)) { 2050 PetscInt rbs, cbs, M, N, i; 2051 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2052 PetscCall(MatGetSize(mat, &M, &N)); 2053 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); 2054 for (i = 0; i < n; i++) 2055 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); 2056 } 2057 if (mat->assembled) { 2058 mat->was_assembled = PETSC_TRUE; 2059 mat->assembled = PETSC_FALSE; 2060 } 2061 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2062 if (mat->ops->setvaluesblocked) { 2063 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2064 } else { 2065 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2066 PetscInt i, j, bs, cbs; 2067 2068 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2069 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2070 iidxm = buf; 2071 iidxn = buf + m * bs; 2072 } else { 2073 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2074 iidxm = bufr; 2075 iidxn = bufc; 2076 } 2077 for (i = 0; i < m; i++) { 2078 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2079 } 2080 if (m != n || bs != cbs || idxm != idxn) { 2081 for (i = 0; i < n; i++) { 2082 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2083 } 2084 } else iidxn = iidxm; 2085 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2086 PetscCall(PetscFree2(bufr, bufc)); 2087 } 2088 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2089 PetscFunctionReturn(PETSC_SUCCESS); 2090 } 2091 2092 /*@C 2093 MatGetValues - Gets a block of local values from a matrix. 2094 2095 Not Collective; can only return values that are owned by the give process 2096 2097 Input Parameters: 2098 + mat - the matrix 2099 . v - a logically two-dimensional array for storing the values 2100 . m - the number of rows 2101 . idxm - the global indices of the rows 2102 . n - the number of columns 2103 - idxn - the global indices of the columns 2104 2105 Level: advanced 2106 2107 Notes: 2108 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2109 The values, `v`, are then returned in a row-oriented format, 2110 analogous to that used by default in `MatSetValues()`. 2111 2112 `MatGetValues()` uses 0-based row and column numbers in 2113 Fortran as well as in C. 2114 2115 `MatGetValues()` requires that the matrix has been assembled 2116 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2117 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2118 without intermediate matrix assembly. 2119 2120 Negative row or column indices will be ignored and those locations in `v` will be 2121 left unchanged. 2122 2123 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2124 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2125 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2126 2127 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2128 @*/ 2129 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2130 { 2131 PetscFunctionBegin; 2132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2133 PetscValidType(mat, 1); 2134 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2135 PetscAssertPointer(idxm, 3); 2136 PetscAssertPointer(idxn, 5); 2137 PetscAssertPointer(v, 6); 2138 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2139 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2140 MatCheckPreallocated(mat, 1); 2141 2142 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2143 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2144 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2145 PetscFunctionReturn(PETSC_SUCCESS); 2146 } 2147 2148 /*@C 2149 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2150 defined previously by `MatSetLocalToGlobalMapping()` 2151 2152 Not Collective 2153 2154 Input Parameters: 2155 + mat - the matrix 2156 . nrow - number of rows 2157 . irow - the row local indices 2158 . ncol - number of columns 2159 - icol - the column local indices 2160 2161 Output Parameter: 2162 . y - a logically two-dimensional array of values 2163 2164 Level: advanced 2165 2166 Notes: 2167 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2168 2169 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, 2170 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2171 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2172 with `MatSetLocalToGlobalMapping()`. 2173 2174 Developer Note: 2175 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2176 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2177 2178 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2179 `MatSetValuesLocal()`, `MatGetValues()` 2180 @*/ 2181 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2182 { 2183 PetscFunctionBeginHot; 2184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2185 PetscValidType(mat, 1); 2186 MatCheckPreallocated(mat, 1); 2187 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2188 PetscAssertPointer(irow, 3); 2189 PetscAssertPointer(icol, 5); 2190 if (PetscDefined(USE_DEBUG)) { 2191 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2192 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2193 } 2194 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2195 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2196 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2197 else { 2198 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2199 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2200 irowm = buf; 2201 icolm = buf + nrow; 2202 } else { 2203 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2204 irowm = bufr; 2205 icolm = bufc; 2206 } 2207 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2208 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2209 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2210 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2211 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2212 PetscCall(PetscFree2(bufr, bufc)); 2213 } 2214 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2215 PetscFunctionReturn(PETSC_SUCCESS); 2216 } 2217 2218 /*@ 2219 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2220 the same size. Currently, this can only be called once and creates the given matrix. 2221 2222 Not Collective 2223 2224 Input Parameters: 2225 + mat - the matrix 2226 . nb - the number of blocks 2227 . bs - the number of rows (and columns) in each block 2228 . rows - a concatenation of the rows for each block 2229 - v - a concatenation of logically two-dimensional arrays of values 2230 2231 Level: advanced 2232 2233 Notes: 2234 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2235 2236 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2237 2238 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2239 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2240 @*/ 2241 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2242 { 2243 PetscFunctionBegin; 2244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2245 PetscValidType(mat, 1); 2246 PetscAssertPointer(rows, 4); 2247 PetscAssertPointer(v, 5); 2248 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2249 2250 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2251 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2252 else { 2253 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2254 } 2255 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2256 PetscFunctionReturn(PETSC_SUCCESS); 2257 } 2258 2259 /*@ 2260 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2261 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2262 using a local (per-processor) numbering. 2263 2264 Not Collective 2265 2266 Input Parameters: 2267 + x - the matrix 2268 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2269 - cmapping - column mapping 2270 2271 Level: intermediate 2272 2273 Note: 2274 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2275 2276 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2277 @*/ 2278 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2279 { 2280 PetscFunctionBegin; 2281 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2282 PetscValidType(x, 1); 2283 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2284 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2285 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2286 else { 2287 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2288 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2289 } 2290 PetscFunctionReturn(PETSC_SUCCESS); 2291 } 2292 2293 /*@ 2294 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2295 2296 Not Collective 2297 2298 Input Parameter: 2299 . A - the matrix 2300 2301 Output Parameters: 2302 + rmapping - row mapping 2303 - cmapping - column mapping 2304 2305 Level: advanced 2306 2307 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2308 @*/ 2309 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2310 { 2311 PetscFunctionBegin; 2312 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2313 PetscValidType(A, 1); 2314 if (rmapping) { 2315 PetscAssertPointer(rmapping, 2); 2316 *rmapping = A->rmap->mapping; 2317 } 2318 if (cmapping) { 2319 PetscAssertPointer(cmapping, 3); 2320 *cmapping = A->cmap->mapping; 2321 } 2322 PetscFunctionReturn(PETSC_SUCCESS); 2323 } 2324 2325 /*@ 2326 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2327 2328 Logically Collective 2329 2330 Input Parameters: 2331 + A - the matrix 2332 . rmap - row layout 2333 - cmap - column layout 2334 2335 Level: advanced 2336 2337 Note: 2338 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2339 2340 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2341 @*/ 2342 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2343 { 2344 PetscFunctionBegin; 2345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2346 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2347 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2348 PetscFunctionReturn(PETSC_SUCCESS); 2349 } 2350 2351 /*@ 2352 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2353 2354 Not Collective 2355 2356 Input Parameter: 2357 . A - the matrix 2358 2359 Output Parameters: 2360 + rmap - row layout 2361 - cmap - column layout 2362 2363 Level: advanced 2364 2365 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2366 @*/ 2367 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2368 { 2369 PetscFunctionBegin; 2370 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2371 PetscValidType(A, 1); 2372 if (rmap) { 2373 PetscAssertPointer(rmap, 2); 2374 *rmap = A->rmap; 2375 } 2376 if (cmap) { 2377 PetscAssertPointer(cmap, 3); 2378 *cmap = A->cmap; 2379 } 2380 PetscFunctionReturn(PETSC_SUCCESS); 2381 } 2382 2383 /*@C 2384 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2385 using a local numbering of the rows and columns. 2386 2387 Not Collective 2388 2389 Input Parameters: 2390 + mat - the matrix 2391 . nrow - number of rows 2392 . irow - the row local indices 2393 . ncol - number of columns 2394 . icol - the column local indices 2395 . y - a logically two-dimensional array of values 2396 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2397 2398 Level: intermediate 2399 2400 Notes: 2401 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2402 2403 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2404 options cannot be mixed without intervening calls to the assembly 2405 routines. 2406 2407 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2408 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2409 2410 Developer Note: 2411 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2412 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2413 2414 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2415 `MatGetValuesLocal()` 2416 @*/ 2417 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2418 { 2419 PetscFunctionBeginHot; 2420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2421 PetscValidType(mat, 1); 2422 MatCheckPreallocated(mat, 1); 2423 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2424 PetscAssertPointer(irow, 3); 2425 PetscAssertPointer(icol, 5); 2426 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2427 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2428 if (PetscDefined(USE_DEBUG)) { 2429 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2430 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2431 } 2432 2433 if (mat->assembled) { 2434 mat->was_assembled = PETSC_TRUE; 2435 mat->assembled = PETSC_FALSE; 2436 } 2437 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2438 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2439 else { 2440 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2441 const PetscInt *irowm, *icolm; 2442 2443 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2444 bufr = buf; 2445 bufc = buf + nrow; 2446 irowm = bufr; 2447 icolm = bufc; 2448 } else { 2449 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2450 irowm = bufr; 2451 icolm = bufc; 2452 } 2453 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2454 else irowm = irow; 2455 if (mat->cmap->mapping) { 2456 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2457 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2458 } else icolm = irowm; 2459 } else icolm = icol; 2460 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2461 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2462 } 2463 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2464 PetscFunctionReturn(PETSC_SUCCESS); 2465 } 2466 2467 /*@C 2468 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2469 using a local ordering of the nodes a block at a time. 2470 2471 Not Collective 2472 2473 Input Parameters: 2474 + mat - the matrix 2475 . nrow - number of rows 2476 . irow - the row local indices 2477 . ncol - number of columns 2478 . icol - the column local indices 2479 . y - a logically two-dimensional array of values 2480 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2481 2482 Level: intermediate 2483 2484 Notes: 2485 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2486 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2487 2488 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2489 options cannot be mixed without intervening calls to the assembly 2490 routines. 2491 2492 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2493 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2494 2495 Developer Note: 2496 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2497 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2498 2499 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2500 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2501 @*/ 2502 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2503 { 2504 PetscFunctionBeginHot; 2505 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2506 PetscValidType(mat, 1); 2507 MatCheckPreallocated(mat, 1); 2508 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2509 PetscAssertPointer(irow, 3); 2510 PetscAssertPointer(icol, 5); 2511 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2512 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2513 if (PetscDefined(USE_DEBUG)) { 2514 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2515 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); 2516 } 2517 2518 if (mat->assembled) { 2519 mat->was_assembled = PETSC_TRUE; 2520 mat->assembled = PETSC_FALSE; 2521 } 2522 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2523 PetscInt irbs, rbs; 2524 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2525 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2526 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2527 } 2528 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2529 PetscInt icbs, cbs; 2530 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2531 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2532 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2533 } 2534 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2535 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2536 else { 2537 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2538 const PetscInt *irowm, *icolm; 2539 2540 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2541 bufr = buf; 2542 bufc = buf + nrow; 2543 irowm = bufr; 2544 icolm = bufc; 2545 } else { 2546 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2547 irowm = bufr; 2548 icolm = bufc; 2549 } 2550 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2551 else irowm = irow; 2552 if (mat->cmap->mapping) { 2553 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2554 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2555 } else icolm = irowm; 2556 } else icolm = icol; 2557 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2558 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2559 } 2560 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2561 PetscFunctionReturn(PETSC_SUCCESS); 2562 } 2563 2564 /*@ 2565 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2566 2567 Collective 2568 2569 Input Parameters: 2570 + mat - the matrix 2571 - x - the vector to be multiplied 2572 2573 Output Parameter: 2574 . y - the result 2575 2576 Level: developer 2577 2578 Note: 2579 The vectors `x` and `y` cannot be the same. I.e., one cannot 2580 call `MatMultDiagonalBlock`(A,y,y). 2581 2582 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2583 @*/ 2584 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2585 { 2586 PetscFunctionBegin; 2587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2588 PetscValidType(mat, 1); 2589 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2590 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2591 2592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2593 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2594 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2595 MatCheckPreallocated(mat, 1); 2596 2597 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2598 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2599 PetscFunctionReturn(PETSC_SUCCESS); 2600 } 2601 2602 /*@ 2603 MatMult - Computes the matrix-vector product, $y = Ax$. 2604 2605 Neighbor-wise Collective 2606 2607 Input Parameters: 2608 + mat - the matrix 2609 - x - the vector to be multiplied 2610 2611 Output Parameter: 2612 . y - the result 2613 2614 Level: beginner 2615 2616 Note: 2617 The vectors `x` and `y` cannot be the same. I.e., one cannot 2618 call `MatMult`(A,y,y). 2619 2620 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2621 @*/ 2622 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2623 { 2624 PetscFunctionBegin; 2625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2626 PetscValidType(mat, 1); 2627 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2628 VecCheckAssembled(x); 2629 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2630 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2631 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2632 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2633 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); 2634 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); 2635 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); 2636 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); 2637 PetscCall(VecSetErrorIfLocked(y, 3)); 2638 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2639 MatCheckPreallocated(mat, 1); 2640 2641 PetscCall(VecLockReadPush(x)); 2642 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2643 PetscUseTypeMethod(mat, mult, x, y); 2644 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2645 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2646 PetscCall(VecLockReadPop(x)); 2647 PetscFunctionReturn(PETSC_SUCCESS); 2648 } 2649 2650 /*@ 2651 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2652 2653 Neighbor-wise Collective 2654 2655 Input Parameters: 2656 + mat - the matrix 2657 - x - the vector to be multiplied 2658 2659 Output Parameter: 2660 . y - the result 2661 2662 Level: beginner 2663 2664 Notes: 2665 The vectors `x` and `y` cannot be the same. I.e., one cannot 2666 call `MatMultTranspose`(A,y,y). 2667 2668 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2669 use `MatMultHermitianTranspose()` 2670 2671 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2672 @*/ 2673 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2674 { 2675 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2676 2677 PetscFunctionBegin; 2678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2679 PetscValidType(mat, 1); 2680 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2681 VecCheckAssembled(x); 2682 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2683 2684 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2685 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2686 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2687 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); 2688 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); 2689 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); 2690 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); 2691 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2692 MatCheckPreallocated(mat, 1); 2693 2694 if (!mat->ops->multtranspose) { 2695 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2696 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); 2697 } else op = mat->ops->multtranspose; 2698 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2699 PetscCall(VecLockReadPush(x)); 2700 PetscCall((*op)(mat, x, y)); 2701 PetscCall(VecLockReadPop(x)); 2702 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2703 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2704 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2705 PetscFunctionReturn(PETSC_SUCCESS); 2706 } 2707 2708 /*@ 2709 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2710 2711 Neighbor-wise Collective 2712 2713 Input Parameters: 2714 + mat - the matrix 2715 - x - the vector to be multiplied 2716 2717 Output Parameter: 2718 . y - the result 2719 2720 Level: beginner 2721 2722 Notes: 2723 The vectors `x` and `y` cannot be the same. I.e., one cannot 2724 call `MatMultHermitianTranspose`(A,y,y). 2725 2726 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2727 2728 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2729 2730 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2731 @*/ 2732 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2733 { 2734 PetscFunctionBegin; 2735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2736 PetscValidType(mat, 1); 2737 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2738 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2739 2740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2742 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2743 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2744 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2745 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2746 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2747 MatCheckPreallocated(mat, 1); 2748 2749 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2750 #if defined(PETSC_USE_COMPLEX) 2751 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2752 PetscCall(VecLockReadPush(x)); 2753 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2754 else PetscUseTypeMethod(mat, mult, x, y); 2755 PetscCall(VecLockReadPop(x)); 2756 } else { 2757 Vec w; 2758 PetscCall(VecDuplicate(x, &w)); 2759 PetscCall(VecCopy(x, w)); 2760 PetscCall(VecConjugate(w)); 2761 PetscCall(MatMultTranspose(mat, w, y)); 2762 PetscCall(VecDestroy(&w)); 2763 PetscCall(VecConjugate(y)); 2764 } 2765 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2766 #else 2767 PetscCall(MatMultTranspose(mat, x, y)); 2768 #endif 2769 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2770 PetscFunctionReturn(PETSC_SUCCESS); 2771 } 2772 2773 /*@ 2774 MatMultAdd - Computes $v3 = v2 + A * v1$. 2775 2776 Neighbor-wise Collective 2777 2778 Input Parameters: 2779 + mat - the matrix 2780 . v1 - the vector to be multiplied by `mat` 2781 - v2 - the vector to be added to the result 2782 2783 Output Parameter: 2784 . v3 - the result 2785 2786 Level: beginner 2787 2788 Note: 2789 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2790 call `MatMultAdd`(A,v1,v2,v1). 2791 2792 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2793 @*/ 2794 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2795 { 2796 PetscFunctionBegin; 2797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2798 PetscValidType(mat, 1); 2799 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2800 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2801 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2802 2803 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2804 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2805 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); 2806 /* 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); 2807 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); */ 2808 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); 2809 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); 2810 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2811 MatCheckPreallocated(mat, 1); 2812 2813 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2814 PetscCall(VecLockReadPush(v1)); 2815 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2816 PetscCall(VecLockReadPop(v1)); 2817 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2818 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2819 PetscFunctionReturn(PETSC_SUCCESS); 2820 } 2821 2822 /*@ 2823 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2824 2825 Neighbor-wise Collective 2826 2827 Input Parameters: 2828 + mat - the matrix 2829 . v1 - the vector to be multiplied by the transpose of the matrix 2830 - v2 - the vector to be added to the result 2831 2832 Output Parameter: 2833 . v3 - the result 2834 2835 Level: beginner 2836 2837 Note: 2838 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2839 call `MatMultTransposeAdd`(A,v1,v2,v1). 2840 2841 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2842 @*/ 2843 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2844 { 2845 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2846 2847 PetscFunctionBegin; 2848 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2849 PetscValidType(mat, 1); 2850 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2851 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2852 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2853 2854 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2855 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2856 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); 2857 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); 2858 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); 2859 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2860 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2861 MatCheckPreallocated(mat, 1); 2862 2863 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2864 PetscCall(VecLockReadPush(v1)); 2865 PetscCall((*op)(mat, v1, v2, v3)); 2866 PetscCall(VecLockReadPop(v1)); 2867 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2868 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2869 PetscFunctionReturn(PETSC_SUCCESS); 2870 } 2871 2872 /*@ 2873 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2874 2875 Neighbor-wise Collective 2876 2877 Input Parameters: 2878 + mat - the matrix 2879 . v1 - the vector to be multiplied by the Hermitian transpose 2880 - v2 - the vector to be added to the result 2881 2882 Output Parameter: 2883 . v3 - the result 2884 2885 Level: beginner 2886 2887 Note: 2888 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2889 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2890 2891 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2892 @*/ 2893 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2894 { 2895 PetscFunctionBegin; 2896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2897 PetscValidType(mat, 1); 2898 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2899 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2900 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2901 2902 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2903 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2904 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2905 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); 2906 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); 2907 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); 2908 MatCheckPreallocated(mat, 1); 2909 2910 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2911 PetscCall(VecLockReadPush(v1)); 2912 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2913 else { 2914 Vec w, z; 2915 PetscCall(VecDuplicate(v1, &w)); 2916 PetscCall(VecCopy(v1, w)); 2917 PetscCall(VecConjugate(w)); 2918 PetscCall(VecDuplicate(v3, &z)); 2919 PetscCall(MatMultTranspose(mat, w, z)); 2920 PetscCall(VecDestroy(&w)); 2921 PetscCall(VecConjugate(z)); 2922 if (v2 != v3) { 2923 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2924 } else { 2925 PetscCall(VecAXPY(v3, 1.0, z)); 2926 } 2927 PetscCall(VecDestroy(&z)); 2928 } 2929 PetscCall(VecLockReadPop(v1)); 2930 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2931 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2932 PetscFunctionReturn(PETSC_SUCCESS); 2933 } 2934 2935 /*@ 2936 MatGetFactorType - gets the type of factorization a matrix is 2937 2938 Not Collective 2939 2940 Input Parameter: 2941 . mat - the matrix 2942 2943 Output Parameter: 2944 . 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` 2945 2946 Level: intermediate 2947 2948 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2949 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2950 @*/ 2951 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2952 { 2953 PetscFunctionBegin; 2954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2955 PetscValidType(mat, 1); 2956 PetscAssertPointer(t, 2); 2957 *t = mat->factortype; 2958 PetscFunctionReturn(PETSC_SUCCESS); 2959 } 2960 2961 /*@ 2962 MatSetFactorType - sets the type of factorization a matrix is 2963 2964 Logically Collective 2965 2966 Input Parameters: 2967 + mat - the matrix 2968 - 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` 2969 2970 Level: intermediate 2971 2972 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2973 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2974 @*/ 2975 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2976 { 2977 PetscFunctionBegin; 2978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2979 PetscValidType(mat, 1); 2980 mat->factortype = t; 2981 PetscFunctionReturn(PETSC_SUCCESS); 2982 } 2983 2984 /*@C 2985 MatGetInfo - Returns information about matrix storage (number of 2986 nonzeros, memory, etc.). 2987 2988 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2989 2990 Input Parameters: 2991 + mat - the matrix 2992 - 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) 2993 2994 Output Parameter: 2995 . info - matrix information context 2996 2997 Options Database Key: 2998 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2999 3000 Notes: 3001 The `MatInfo` context contains a variety of matrix data, including 3002 number of nonzeros allocated and used, number of mallocs during 3003 matrix assembly, etc. Additional information for factored matrices 3004 is provided (such as the fill ratio, number of mallocs during 3005 factorization, etc.). 3006 3007 Example: 3008 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3009 data within the MatInfo context. For example, 3010 .vb 3011 MatInfo info; 3012 Mat A; 3013 double mal, nz_a, nz_u; 3014 3015 MatGetInfo(A, MAT_LOCAL, &info); 3016 mal = info.mallocs; 3017 nz_a = info.nz_allocated; 3018 .ve 3019 3020 Fortran users should declare info as a double precision 3021 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3022 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3023 a complete list of parameter names. 3024 .vb 3025 double precision info(MAT_INFO_SIZE) 3026 double precision mal, nz_a 3027 Mat A 3028 integer ierr 3029 3030 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3031 mal = info(MAT_INFO_MALLOCS) 3032 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3033 .ve 3034 3035 Level: intermediate 3036 3037 Developer Note: 3038 The Fortran interface is not autogenerated as the 3039 interface definition cannot be generated correctly [due to `MatInfo` argument] 3040 3041 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3042 @*/ 3043 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3044 { 3045 PetscFunctionBegin; 3046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3047 PetscValidType(mat, 1); 3048 PetscAssertPointer(info, 3); 3049 MatCheckPreallocated(mat, 1); 3050 PetscUseTypeMethod(mat, getinfo, flag, info); 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /* 3055 This is used by external packages where it is not easy to get the info from the actual 3056 matrix factorization. 3057 */ 3058 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3059 { 3060 PetscFunctionBegin; 3061 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3062 PetscFunctionReturn(PETSC_SUCCESS); 3063 } 3064 3065 /*@C 3066 MatLUFactor - Performs in-place LU factorization of matrix. 3067 3068 Collective 3069 3070 Input Parameters: 3071 + mat - the matrix 3072 . row - row permutation 3073 . col - column permutation 3074 - info - options for factorization, includes 3075 .vb 3076 fill - expected fill as ratio of original fill. 3077 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3078 Run with the option -info to determine an optimal value to use 3079 .ve 3080 3081 Level: developer 3082 3083 Notes: 3084 Most users should employ the `KSP` interface for linear solvers 3085 instead of working directly with matrix algebra routines such as this. 3086 See, e.g., `KSPCreate()`. 3087 3088 This changes the state of the matrix to a factored matrix; it cannot be used 3089 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3090 3091 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3092 when not using `KSP`. 3093 3094 Developer Note: 3095 The Fortran interface is not autogenerated as the 3096 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3097 3098 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3099 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3100 @*/ 3101 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3102 { 3103 MatFactorInfo tinfo; 3104 3105 PetscFunctionBegin; 3106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3107 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3108 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3109 if (info) PetscAssertPointer(info, 4); 3110 PetscValidType(mat, 1); 3111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3112 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3113 MatCheckPreallocated(mat, 1); 3114 if (!info) { 3115 PetscCall(MatFactorInfoInitialize(&tinfo)); 3116 info = &tinfo; 3117 } 3118 3119 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3120 PetscUseTypeMethod(mat, lufactor, row, col, info); 3121 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3122 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3123 PetscFunctionReturn(PETSC_SUCCESS); 3124 } 3125 3126 /*@C 3127 MatILUFactor - Performs in-place ILU factorization of matrix. 3128 3129 Collective 3130 3131 Input Parameters: 3132 + mat - the matrix 3133 . row - row permutation 3134 . col - column permutation 3135 - info - structure containing 3136 .vb 3137 levels - number of levels of fill. 3138 expected fill - as ratio of original fill. 3139 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3140 missing diagonal entries) 3141 .ve 3142 3143 Level: developer 3144 3145 Notes: 3146 Most users should employ the `KSP` interface for linear solvers 3147 instead of working directly with matrix algebra routines such as this. 3148 See, e.g., `KSPCreate()`. 3149 3150 Probably really in-place only when level of fill is zero, otherwise allocates 3151 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3152 when not using `KSP`. 3153 3154 Developer Note: 3155 The Fortran interface is not autogenerated as the 3156 interface definition cannot be generated correctly [due to MatFactorInfo] 3157 3158 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3159 @*/ 3160 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3161 { 3162 PetscFunctionBegin; 3163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3164 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3165 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3166 PetscAssertPointer(info, 4); 3167 PetscValidType(mat, 1); 3168 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3169 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3170 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3171 MatCheckPreallocated(mat, 1); 3172 3173 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3174 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3175 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3176 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3177 PetscFunctionReturn(PETSC_SUCCESS); 3178 } 3179 3180 /*@C 3181 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3182 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3183 3184 Collective 3185 3186 Input Parameters: 3187 + fact - the factor matrix obtained with `MatGetFactor()` 3188 . mat - the matrix 3189 . row - the row permutation 3190 . col - the column permutation 3191 - info - options for factorization, includes 3192 .vb 3193 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3194 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3195 .ve 3196 3197 Level: developer 3198 3199 Notes: 3200 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3201 3202 Most users should employ the simplified `KSP` interface for linear solvers 3203 instead of working directly with matrix algebra routines such as this. 3204 See, e.g., `KSPCreate()`. 3205 3206 Developer Note: 3207 The Fortran interface is not autogenerated as the 3208 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3209 3210 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3211 @*/ 3212 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3213 { 3214 MatFactorInfo tinfo; 3215 3216 PetscFunctionBegin; 3217 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3218 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3219 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3220 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3221 if (info) PetscAssertPointer(info, 5); 3222 PetscValidType(fact, 1); 3223 PetscValidType(mat, 2); 3224 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3225 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3226 MatCheckPreallocated(mat, 2); 3227 if (!info) { 3228 PetscCall(MatFactorInfoInitialize(&tinfo)); 3229 info = &tinfo; 3230 } 3231 3232 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3233 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3234 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3235 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3236 PetscFunctionReturn(PETSC_SUCCESS); 3237 } 3238 3239 /*@C 3240 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3241 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3242 3243 Collective 3244 3245 Input Parameters: 3246 + fact - the factor matrix obtained with `MatGetFactor()` 3247 . mat - the matrix 3248 - info - options for factorization 3249 3250 Level: developer 3251 3252 Notes: 3253 See `MatLUFactor()` for in-place factorization. See 3254 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3255 3256 Most users should employ the `KSP` interface for linear solvers 3257 instead of working directly with matrix algebra routines such as this. 3258 See, e.g., `KSPCreate()`. 3259 3260 Developer Note: 3261 The Fortran interface is not autogenerated as the 3262 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3263 3264 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3265 @*/ 3266 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3267 { 3268 MatFactorInfo tinfo; 3269 3270 PetscFunctionBegin; 3271 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3272 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3273 PetscValidType(fact, 1); 3274 PetscValidType(mat, 2); 3275 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3276 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, 3277 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3278 3279 MatCheckPreallocated(mat, 2); 3280 if (!info) { 3281 PetscCall(MatFactorInfoInitialize(&tinfo)); 3282 info = &tinfo; 3283 } 3284 3285 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3286 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3287 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3288 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3289 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3290 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3291 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3292 PetscFunctionReturn(PETSC_SUCCESS); 3293 } 3294 3295 /*@C 3296 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3297 symmetric matrix. 3298 3299 Collective 3300 3301 Input Parameters: 3302 + mat - the matrix 3303 . perm - row and column permutations 3304 - info - expected fill as ratio of original fill 3305 3306 Level: developer 3307 3308 Notes: 3309 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3310 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3311 3312 Most users should employ the `KSP` interface for linear solvers 3313 instead of working directly with matrix algebra routines such as this. 3314 See, e.g., `KSPCreate()`. 3315 3316 Developer Note: 3317 The Fortran interface is not autogenerated as the 3318 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3319 3320 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3321 `MatGetOrdering()` 3322 @*/ 3323 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3324 { 3325 MatFactorInfo tinfo; 3326 3327 PetscFunctionBegin; 3328 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3329 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3330 if (info) PetscAssertPointer(info, 3); 3331 PetscValidType(mat, 1); 3332 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3333 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3334 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3335 MatCheckPreallocated(mat, 1); 3336 if (!info) { 3337 PetscCall(MatFactorInfoInitialize(&tinfo)); 3338 info = &tinfo; 3339 } 3340 3341 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3342 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3343 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3344 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3345 PetscFunctionReturn(PETSC_SUCCESS); 3346 } 3347 3348 /*@C 3349 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3350 of a symmetric matrix. 3351 3352 Collective 3353 3354 Input Parameters: 3355 + fact - the factor matrix obtained with `MatGetFactor()` 3356 . mat - the matrix 3357 . perm - row and column permutations 3358 - info - options for factorization, includes 3359 .vb 3360 fill - expected fill as ratio of original fill. 3361 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3362 Run with the option -info to determine an optimal value to use 3363 .ve 3364 3365 Level: developer 3366 3367 Notes: 3368 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3369 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3370 3371 Most users should employ the `KSP` interface for linear solvers 3372 instead of working directly with matrix algebra routines such as this. 3373 See, e.g., `KSPCreate()`. 3374 3375 Developer Note: 3376 The Fortran interface is not autogenerated as the 3377 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3378 3379 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3380 `MatGetOrdering()` 3381 @*/ 3382 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3383 { 3384 MatFactorInfo tinfo; 3385 3386 PetscFunctionBegin; 3387 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3388 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3389 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3390 if (info) PetscAssertPointer(info, 4); 3391 PetscValidType(fact, 1); 3392 PetscValidType(mat, 2); 3393 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3394 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3395 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3396 MatCheckPreallocated(mat, 2); 3397 if (!info) { 3398 PetscCall(MatFactorInfoInitialize(&tinfo)); 3399 info = &tinfo; 3400 } 3401 3402 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3403 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3404 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3405 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3406 PetscFunctionReturn(PETSC_SUCCESS); 3407 } 3408 3409 /*@C 3410 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3411 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3412 `MatCholeskyFactorSymbolic()`. 3413 3414 Collective 3415 3416 Input Parameters: 3417 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3418 . mat - the initial matrix that is to be factored 3419 - info - options for factorization 3420 3421 Level: developer 3422 3423 Note: 3424 Most users should employ the `KSP` interface for linear solvers 3425 instead of working directly with matrix algebra routines such as this. 3426 See, e.g., `KSPCreate()`. 3427 3428 Developer Note: 3429 The Fortran interface is not autogenerated as the 3430 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3431 3432 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3433 @*/ 3434 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3435 { 3436 MatFactorInfo tinfo; 3437 3438 PetscFunctionBegin; 3439 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3441 PetscValidType(fact, 1); 3442 PetscValidType(mat, 2); 3443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3444 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, 3445 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3446 MatCheckPreallocated(mat, 2); 3447 if (!info) { 3448 PetscCall(MatFactorInfoInitialize(&tinfo)); 3449 info = &tinfo; 3450 } 3451 3452 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3453 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3454 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3455 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3456 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3457 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3458 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3459 PetscFunctionReturn(PETSC_SUCCESS); 3460 } 3461 3462 /*@ 3463 MatQRFactor - Performs in-place QR factorization of matrix. 3464 3465 Collective 3466 3467 Input Parameters: 3468 + mat - the matrix 3469 . col - column permutation 3470 - info - options for factorization, includes 3471 .vb 3472 fill - expected fill as ratio of original fill. 3473 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3474 Run with the option -info to determine an optimal value to use 3475 .ve 3476 3477 Level: developer 3478 3479 Notes: 3480 Most users should employ the `KSP` interface for linear solvers 3481 instead of working directly with matrix algebra routines such as this. 3482 See, e.g., `KSPCreate()`. 3483 3484 This changes the state of the matrix to a factored matrix; it cannot be used 3485 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3486 3487 Developer Note: 3488 The Fortran interface is not autogenerated as the 3489 interface definition cannot be generated correctly [due to MatFactorInfo] 3490 3491 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3492 `MatSetUnfactored()` 3493 @*/ 3494 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3495 { 3496 PetscFunctionBegin; 3497 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3498 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3499 if (info) PetscAssertPointer(info, 3); 3500 PetscValidType(mat, 1); 3501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3503 MatCheckPreallocated(mat, 1); 3504 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3505 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3506 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3507 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3508 PetscFunctionReturn(PETSC_SUCCESS); 3509 } 3510 3511 /*@ 3512 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3513 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3514 3515 Collective 3516 3517 Input Parameters: 3518 + fact - the factor matrix obtained with `MatGetFactor()` 3519 . mat - the matrix 3520 . col - column permutation 3521 - info - options for factorization, includes 3522 .vb 3523 fill - expected fill as ratio of original fill. 3524 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3525 Run with the option -info to determine an optimal value to use 3526 .ve 3527 3528 Level: developer 3529 3530 Note: 3531 Most users should employ the `KSP` interface for linear solvers 3532 instead of working directly with matrix algebra routines such as this. 3533 See, e.g., `KSPCreate()`. 3534 3535 Developer Note: 3536 The Fortran interface is not autogenerated as the 3537 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3538 3539 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3540 @*/ 3541 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3542 { 3543 MatFactorInfo tinfo; 3544 3545 PetscFunctionBegin; 3546 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3548 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3549 if (info) PetscAssertPointer(info, 4); 3550 PetscValidType(fact, 1); 3551 PetscValidType(mat, 2); 3552 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3553 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3554 MatCheckPreallocated(mat, 2); 3555 if (!info) { 3556 PetscCall(MatFactorInfoInitialize(&tinfo)); 3557 info = &tinfo; 3558 } 3559 3560 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3561 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3562 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3563 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3564 PetscFunctionReturn(PETSC_SUCCESS); 3565 } 3566 3567 /*@ 3568 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3569 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3570 3571 Collective 3572 3573 Input Parameters: 3574 + fact - the factor matrix obtained with `MatGetFactor()` 3575 . mat - the matrix 3576 - info - options for factorization 3577 3578 Level: developer 3579 3580 Notes: 3581 See `MatQRFactor()` for in-place factorization. 3582 3583 Most users should employ the `KSP` interface for linear solvers 3584 instead of working directly with matrix algebra routines such as this. 3585 See, e.g., `KSPCreate()`. 3586 3587 Developer Note: 3588 The Fortran interface is not autogenerated as the 3589 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3590 3591 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3592 @*/ 3593 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3594 { 3595 MatFactorInfo tinfo; 3596 3597 PetscFunctionBegin; 3598 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3600 PetscValidType(fact, 1); 3601 PetscValidType(mat, 2); 3602 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3603 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, 3604 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3605 3606 MatCheckPreallocated(mat, 2); 3607 if (!info) { 3608 PetscCall(MatFactorInfoInitialize(&tinfo)); 3609 info = &tinfo; 3610 } 3611 3612 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3613 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3614 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3615 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3616 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3617 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3618 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3619 PetscFunctionReturn(PETSC_SUCCESS); 3620 } 3621 3622 /*@ 3623 MatSolve - Solves $A x = b$, given a factored matrix. 3624 3625 Neighbor-wise Collective 3626 3627 Input Parameters: 3628 + mat - the factored matrix 3629 - b - the right-hand-side vector 3630 3631 Output Parameter: 3632 . x - the result vector 3633 3634 Level: developer 3635 3636 Notes: 3637 The vectors `b` and `x` cannot be the same. I.e., one cannot 3638 call `MatSolve`(A,x,x). 3639 3640 Most users should employ the `KSP` interface for linear solvers 3641 instead of working directly with matrix algebra routines such as this. 3642 See, e.g., `KSPCreate()`. 3643 3644 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3645 @*/ 3646 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3647 { 3648 PetscFunctionBegin; 3649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3650 PetscValidType(mat, 1); 3651 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3652 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3653 PetscCheckSameComm(mat, 1, b, 2); 3654 PetscCheckSameComm(mat, 1, x, 3); 3655 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3656 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); 3657 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); 3658 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); 3659 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3660 MatCheckPreallocated(mat, 1); 3661 3662 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3663 if (mat->factorerrortype) { 3664 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3665 PetscCall(VecSetInf(x)); 3666 } else PetscUseTypeMethod(mat, solve, b, x); 3667 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3668 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3669 PetscFunctionReturn(PETSC_SUCCESS); 3670 } 3671 3672 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3673 { 3674 Vec b, x; 3675 PetscInt N, i; 3676 PetscErrorCode (*f)(Mat, Vec, Vec); 3677 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3678 3679 PetscFunctionBegin; 3680 if (A->factorerrortype) { 3681 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3682 PetscCall(MatSetInf(X)); 3683 PetscFunctionReturn(PETSC_SUCCESS); 3684 } 3685 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3686 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3687 PetscCall(MatBoundToCPU(A, &Abound)); 3688 if (!Abound) { 3689 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3690 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3691 } 3692 #if PetscDefined(HAVE_CUDA) 3693 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3694 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3695 #elif PetscDefined(HAVE_HIP) 3696 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3697 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3698 #endif 3699 PetscCall(MatGetSize(B, NULL, &N)); 3700 for (i = 0; i < N; i++) { 3701 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3702 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3703 PetscCall((*f)(A, b, x)); 3704 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3705 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3706 } 3707 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3708 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3709 PetscFunctionReturn(PETSC_SUCCESS); 3710 } 3711 3712 /*@ 3713 MatMatSolve - Solves $A X = B$, given a factored matrix. 3714 3715 Neighbor-wise Collective 3716 3717 Input Parameters: 3718 + A - the factored matrix 3719 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3720 3721 Output Parameter: 3722 . X - the result matrix (dense matrix) 3723 3724 Level: developer 3725 3726 Note: 3727 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3728 otherwise, `B` and `X` cannot be the same. 3729 3730 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3731 @*/ 3732 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3733 { 3734 PetscFunctionBegin; 3735 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3736 PetscValidType(A, 1); 3737 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3738 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3739 PetscCheckSameComm(A, 1, B, 2); 3740 PetscCheckSameComm(A, 1, X, 3); 3741 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); 3742 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); 3743 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"); 3744 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3745 MatCheckPreallocated(A, 1); 3746 3747 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3748 if (!A->ops->matsolve) { 3749 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3750 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3751 } else PetscUseTypeMethod(A, matsolve, B, X); 3752 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3753 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3754 PetscFunctionReturn(PETSC_SUCCESS); 3755 } 3756 3757 /*@ 3758 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3759 3760 Neighbor-wise Collective 3761 3762 Input Parameters: 3763 + A - the factored matrix 3764 - B - the right-hand-side matrix (`MATDENSE` matrix) 3765 3766 Output Parameter: 3767 . X - the result matrix (dense matrix) 3768 3769 Level: developer 3770 3771 Note: 3772 The matrices `B` and `X` cannot be the same. I.e., one cannot 3773 call `MatMatSolveTranspose`(A,X,X). 3774 3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3776 @*/ 3777 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3778 { 3779 PetscFunctionBegin; 3780 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3781 PetscValidType(A, 1); 3782 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3783 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3784 PetscCheckSameComm(A, 1, B, 2); 3785 PetscCheckSameComm(A, 1, X, 3); 3786 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3787 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); 3788 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); 3789 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); 3790 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"); 3791 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3792 MatCheckPreallocated(A, 1); 3793 3794 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3795 if (!A->ops->matsolvetranspose) { 3796 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3797 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3798 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3799 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3800 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3801 PetscFunctionReturn(PETSC_SUCCESS); 3802 } 3803 3804 /*@ 3805 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3806 3807 Neighbor-wise Collective 3808 3809 Input Parameters: 3810 + A - the factored matrix 3811 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3812 3813 Output Parameter: 3814 . X - the result matrix (dense matrix) 3815 3816 Level: developer 3817 3818 Note: 3819 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 3820 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3821 3822 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3823 @*/ 3824 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3825 { 3826 PetscFunctionBegin; 3827 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3828 PetscValidType(A, 1); 3829 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3830 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3831 PetscCheckSameComm(A, 1, Bt, 2); 3832 PetscCheckSameComm(A, 1, X, 3); 3833 3834 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3835 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); 3836 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); 3837 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"); 3838 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3839 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3840 MatCheckPreallocated(A, 1); 3841 3842 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3843 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3844 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3845 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3846 PetscFunctionReturn(PETSC_SUCCESS); 3847 } 3848 3849 /*@ 3850 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3851 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3852 3853 Neighbor-wise Collective 3854 3855 Input Parameters: 3856 + mat - the factored matrix 3857 - b - the right-hand-side vector 3858 3859 Output Parameter: 3860 . x - the result vector 3861 3862 Level: developer 3863 3864 Notes: 3865 `MatSolve()` should be used for most applications, as it performs 3866 a forward solve followed by a backward solve. 3867 3868 The vectors `b` and `x` cannot be the same, i.e., one cannot 3869 call `MatForwardSolve`(A,x,x). 3870 3871 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3872 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3873 `MatForwardSolve()` solves $U^T*D y = b$, and 3874 `MatBackwardSolve()` solves $U x = y$. 3875 Thus they do not provide a symmetric preconditioner. 3876 3877 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3878 @*/ 3879 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3880 { 3881 PetscFunctionBegin; 3882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3883 PetscValidType(mat, 1); 3884 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3885 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3886 PetscCheckSameComm(mat, 1, b, 2); 3887 PetscCheckSameComm(mat, 1, x, 3); 3888 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3889 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); 3890 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); 3891 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); 3892 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3893 MatCheckPreallocated(mat, 1); 3894 3895 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3896 PetscUseTypeMethod(mat, forwardsolve, b, x); 3897 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3898 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3899 PetscFunctionReturn(PETSC_SUCCESS); 3900 } 3901 3902 /*@ 3903 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3904 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3905 3906 Neighbor-wise Collective 3907 3908 Input Parameters: 3909 + mat - the factored matrix 3910 - b - the right-hand-side vector 3911 3912 Output Parameter: 3913 . x - the result vector 3914 3915 Level: developer 3916 3917 Notes: 3918 `MatSolve()` should be used for most applications, as it performs 3919 a forward solve followed by a backward solve. 3920 3921 The vectors `b` and `x` cannot be the same. I.e., one cannot 3922 call `MatBackwardSolve`(A,x,x). 3923 3924 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3925 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3926 `MatForwardSolve()` solves $U^T*D y = b$, and 3927 `MatBackwardSolve()` solves $U x = y$. 3928 Thus they do not provide a symmetric preconditioner. 3929 3930 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3931 @*/ 3932 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3933 { 3934 PetscFunctionBegin; 3935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3936 PetscValidType(mat, 1); 3937 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3938 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3939 PetscCheckSameComm(mat, 1, b, 2); 3940 PetscCheckSameComm(mat, 1, x, 3); 3941 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3942 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); 3943 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); 3944 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); 3945 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3946 MatCheckPreallocated(mat, 1); 3947 3948 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3949 PetscUseTypeMethod(mat, backwardsolve, b, x); 3950 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3951 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3952 PetscFunctionReturn(PETSC_SUCCESS); 3953 } 3954 3955 /*@ 3956 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3957 3958 Neighbor-wise Collective 3959 3960 Input Parameters: 3961 + mat - the factored matrix 3962 . b - the right-hand-side vector 3963 - y - the vector to be added to 3964 3965 Output Parameter: 3966 . x - the result vector 3967 3968 Level: developer 3969 3970 Note: 3971 The vectors `b` and `x` cannot be the same. I.e., one cannot 3972 call `MatSolveAdd`(A,x,y,x). 3973 3974 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3975 @*/ 3976 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3977 { 3978 PetscScalar one = 1.0; 3979 Vec tmp; 3980 3981 PetscFunctionBegin; 3982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3983 PetscValidType(mat, 1); 3984 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3985 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3986 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3987 PetscCheckSameComm(mat, 1, b, 2); 3988 PetscCheckSameComm(mat, 1, y, 3); 3989 PetscCheckSameComm(mat, 1, x, 4); 3990 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3991 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); 3992 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); 3993 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); 3994 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); 3995 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); 3996 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3997 MatCheckPreallocated(mat, 1); 3998 3999 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4000 if (mat->factorerrortype) { 4001 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4002 PetscCall(VecSetInf(x)); 4003 } else if (mat->ops->solveadd) { 4004 PetscUseTypeMethod(mat, solveadd, b, y, x); 4005 } else { 4006 /* do the solve then the add manually */ 4007 if (x != y) { 4008 PetscCall(MatSolve(mat, b, x)); 4009 PetscCall(VecAXPY(x, one, y)); 4010 } else { 4011 PetscCall(VecDuplicate(x, &tmp)); 4012 PetscCall(VecCopy(x, tmp)); 4013 PetscCall(MatSolve(mat, b, x)); 4014 PetscCall(VecAXPY(x, one, tmp)); 4015 PetscCall(VecDestroy(&tmp)); 4016 } 4017 } 4018 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4019 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4020 PetscFunctionReturn(PETSC_SUCCESS); 4021 } 4022 4023 /*@ 4024 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4025 4026 Neighbor-wise Collective 4027 4028 Input Parameters: 4029 + mat - the factored matrix 4030 - b - the right-hand-side vector 4031 4032 Output Parameter: 4033 . x - the result vector 4034 4035 Level: developer 4036 4037 Notes: 4038 The vectors `b` and `x` cannot be the same. I.e., one cannot 4039 call `MatSolveTranspose`(A,x,x). 4040 4041 Most users should employ the `KSP` interface for linear solvers 4042 instead of working directly with matrix algebra routines such as this. 4043 See, e.g., `KSPCreate()`. 4044 4045 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4046 @*/ 4047 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4048 { 4049 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4050 4051 PetscFunctionBegin; 4052 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4053 PetscValidType(mat, 1); 4054 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4055 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4056 PetscCheckSameComm(mat, 1, b, 2); 4057 PetscCheckSameComm(mat, 1, x, 3); 4058 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4059 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); 4060 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); 4061 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4062 MatCheckPreallocated(mat, 1); 4063 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4064 if (mat->factorerrortype) { 4065 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4066 PetscCall(VecSetInf(x)); 4067 } else { 4068 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4069 PetscCall((*f)(mat, b, x)); 4070 } 4071 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4072 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4073 PetscFunctionReturn(PETSC_SUCCESS); 4074 } 4075 4076 /*@ 4077 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4078 factored matrix. 4079 4080 Neighbor-wise Collective 4081 4082 Input Parameters: 4083 + mat - the factored matrix 4084 . b - the right-hand-side vector 4085 - y - the vector to be added to 4086 4087 Output Parameter: 4088 . x - the result vector 4089 4090 Level: developer 4091 4092 Note: 4093 The vectors `b` and `x` cannot be the same. I.e., one cannot 4094 call `MatSolveTransposeAdd`(A,x,y,x). 4095 4096 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4097 @*/ 4098 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4099 { 4100 PetscScalar one = 1.0; 4101 Vec tmp; 4102 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4103 4104 PetscFunctionBegin; 4105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4106 PetscValidType(mat, 1); 4107 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4108 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4109 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4110 PetscCheckSameComm(mat, 1, b, 2); 4111 PetscCheckSameComm(mat, 1, y, 3); 4112 PetscCheckSameComm(mat, 1, x, 4); 4113 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4114 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); 4115 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); 4116 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); 4117 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); 4118 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4119 MatCheckPreallocated(mat, 1); 4120 4121 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4122 if (mat->factorerrortype) { 4123 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4124 PetscCall(VecSetInf(x)); 4125 } else if (f) { 4126 PetscCall((*f)(mat, b, y, x)); 4127 } else { 4128 /* do the solve then the add manually */ 4129 if (x != y) { 4130 PetscCall(MatSolveTranspose(mat, b, x)); 4131 PetscCall(VecAXPY(x, one, y)); 4132 } else { 4133 PetscCall(VecDuplicate(x, &tmp)); 4134 PetscCall(VecCopy(x, tmp)); 4135 PetscCall(MatSolveTranspose(mat, b, x)); 4136 PetscCall(VecAXPY(x, one, tmp)); 4137 PetscCall(VecDestroy(&tmp)); 4138 } 4139 } 4140 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4141 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4142 PetscFunctionReturn(PETSC_SUCCESS); 4143 } 4144 4145 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4146 /*@ 4147 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4148 4149 Neighbor-wise Collective 4150 4151 Input Parameters: 4152 + mat - the matrix 4153 . b - the right-hand side 4154 . omega - the relaxation factor 4155 . flag - flag indicating the type of SOR (see below) 4156 . shift - diagonal shift 4157 . its - the number of iterations 4158 - lits - the number of local iterations 4159 4160 Output Parameter: 4161 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4162 4163 SOR Flags: 4164 + `SOR_FORWARD_SWEEP` - forward SOR 4165 . `SOR_BACKWARD_SWEEP` - backward SOR 4166 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4167 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4168 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4169 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4170 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4171 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4172 upper/lower triangular part of matrix to 4173 vector (with omega) 4174 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4175 4176 Level: developer 4177 4178 Notes: 4179 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4180 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4181 on each processor. 4182 4183 Application programmers will not generally use `MatSOR()` directly, 4184 but instead will employ the `KSP`/`PC` interface. 4185 4186 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4187 4188 Most users should employ the `KSP` interface for linear solvers 4189 instead of working directly with matrix algebra routines such as this. 4190 See, e.g., `KSPCreate()`. 4191 4192 Vectors `x` and `b` CANNOT be the same 4193 4194 The flags are implemented as bitwise inclusive or operations. 4195 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4196 to specify a zero initial guess for SSOR. 4197 4198 Developer Note: 4199 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4200 4201 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4202 @*/ 4203 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4204 { 4205 PetscFunctionBegin; 4206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4207 PetscValidType(mat, 1); 4208 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4209 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4210 PetscCheckSameComm(mat, 1, b, 2); 4211 PetscCheckSameComm(mat, 1, x, 8); 4212 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4213 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4214 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); 4215 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); 4216 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); 4217 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4218 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4219 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4220 4221 MatCheckPreallocated(mat, 1); 4222 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4223 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4224 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4225 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4226 PetscFunctionReturn(PETSC_SUCCESS); 4227 } 4228 4229 /* 4230 Default matrix copy routine. 4231 */ 4232 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4233 { 4234 PetscInt i, rstart = 0, rend = 0, nz; 4235 const PetscInt *cwork; 4236 const PetscScalar *vwork; 4237 4238 PetscFunctionBegin; 4239 if (B->assembled) PetscCall(MatZeroEntries(B)); 4240 if (str == SAME_NONZERO_PATTERN) { 4241 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4242 for (i = rstart; i < rend; i++) { 4243 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4244 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4245 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4246 } 4247 } else { 4248 PetscCall(MatAYPX(B, 0.0, A, str)); 4249 } 4250 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4251 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4252 PetscFunctionReturn(PETSC_SUCCESS); 4253 } 4254 4255 /*@ 4256 MatCopy - Copies a matrix to another matrix. 4257 4258 Collective 4259 4260 Input Parameters: 4261 + A - the matrix 4262 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4263 4264 Output Parameter: 4265 . B - where the copy is put 4266 4267 Level: intermediate 4268 4269 Notes: 4270 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4271 4272 `MatCopy()` copies the matrix entries of a matrix to another existing 4273 matrix (after first zeroing the second matrix). A related routine is 4274 `MatConvert()`, which first creates a new matrix and then copies the data. 4275 4276 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4277 @*/ 4278 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4279 { 4280 PetscInt i; 4281 4282 PetscFunctionBegin; 4283 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4284 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4285 PetscValidType(A, 1); 4286 PetscValidType(B, 2); 4287 PetscCheckSameComm(A, 1, B, 2); 4288 MatCheckPreallocated(B, 2); 4289 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4290 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4291 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, 4292 A->cmap->N, B->cmap->N); 4293 MatCheckPreallocated(A, 1); 4294 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4295 4296 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4297 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4298 else PetscCall(MatCopy_Basic(A, B, str)); 4299 4300 B->stencil.dim = A->stencil.dim; 4301 B->stencil.noc = A->stencil.noc; 4302 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4303 B->stencil.dims[i] = A->stencil.dims[i]; 4304 B->stencil.starts[i] = A->stencil.starts[i]; 4305 } 4306 4307 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4308 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4309 PetscFunctionReturn(PETSC_SUCCESS); 4310 } 4311 4312 /*@ 4313 MatConvert - Converts a matrix to another matrix, either of the same 4314 or different type. 4315 4316 Collective 4317 4318 Input Parameters: 4319 + mat - the matrix 4320 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4321 same type as the original matrix. 4322 - reuse - denotes if the destination matrix is to be created or reused. 4323 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 4324 `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). 4325 4326 Output Parameter: 4327 . M - pointer to place new matrix 4328 4329 Level: intermediate 4330 4331 Notes: 4332 `MatConvert()` first creates a new matrix and then copies the data from 4333 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4334 entries of one matrix to another already existing matrix context. 4335 4336 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4337 the MPI communicator of the generated matrix is always the same as the communicator 4338 of the input matrix. 4339 4340 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4341 @*/ 4342 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4343 { 4344 PetscBool sametype, issame, flg; 4345 PetscBool3 issymmetric, ishermitian; 4346 char convname[256], mtype[256]; 4347 Mat B; 4348 4349 PetscFunctionBegin; 4350 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4351 PetscValidType(mat, 1); 4352 PetscAssertPointer(M, 4); 4353 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4354 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4355 MatCheckPreallocated(mat, 1); 4356 4357 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4358 if (flg) newtype = mtype; 4359 4360 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4361 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4362 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4363 if (reuse == MAT_REUSE_MATRIX) { 4364 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4365 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4366 } 4367 4368 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4369 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4370 PetscFunctionReturn(PETSC_SUCCESS); 4371 } 4372 4373 /* Cache Mat options because some converters use MatHeaderReplace */ 4374 issymmetric = mat->symmetric; 4375 ishermitian = mat->hermitian; 4376 4377 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4378 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4379 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4380 } else { 4381 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4382 const char *prefix[3] = {"seq", "mpi", ""}; 4383 PetscInt i; 4384 /* 4385 Order of precedence: 4386 0) See if newtype is a superclass of the current matrix. 4387 1) See if a specialized converter is known to the current matrix. 4388 2) See if a specialized converter is known to the desired matrix class. 4389 3) See if a good general converter is registered for the desired class 4390 (as of 6/27/03 only MATMPIADJ falls into this category). 4391 4) See if a good general converter is known for the current matrix. 4392 5) Use a really basic converter. 4393 */ 4394 4395 /* 0) See if newtype is a superclass of the current matrix. 4396 i.e mat is mpiaij and newtype is aij */ 4397 for (i = 0; i < 2; i++) { 4398 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4399 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4400 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4401 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4402 if (flg) { 4403 if (reuse == MAT_INPLACE_MATRIX) { 4404 PetscCall(PetscInfo(mat, "Early return\n")); 4405 PetscFunctionReturn(PETSC_SUCCESS); 4406 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4407 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4408 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4409 PetscFunctionReturn(PETSC_SUCCESS); 4410 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4411 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4412 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4413 PetscFunctionReturn(PETSC_SUCCESS); 4414 } 4415 } 4416 } 4417 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4418 for (i = 0; i < 3; i++) { 4419 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4420 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4421 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4422 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4423 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4424 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4425 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4426 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4427 if (conv) goto foundconv; 4428 } 4429 4430 /* 2) See if a specialized converter is known to the desired matrix class. */ 4431 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4432 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4433 PetscCall(MatSetType(B, newtype)); 4434 for (i = 0; i < 3; i++) { 4435 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4436 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4437 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4438 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4439 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4440 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4441 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4442 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4443 if (conv) { 4444 PetscCall(MatDestroy(&B)); 4445 goto foundconv; 4446 } 4447 } 4448 4449 /* 3) See if a good general converter is registered for the desired class */ 4450 conv = B->ops->convertfrom; 4451 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4452 PetscCall(MatDestroy(&B)); 4453 if (conv) goto foundconv; 4454 4455 /* 4) See if a good general converter is known for the current matrix */ 4456 if (mat->ops->convert) conv = mat->ops->convert; 4457 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4458 if (conv) goto foundconv; 4459 4460 /* 5) Use a really basic converter. */ 4461 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4462 conv = MatConvert_Basic; 4463 4464 foundconv: 4465 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4466 PetscCall((*conv)(mat, newtype, reuse, M)); 4467 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4468 /* the block sizes must be same if the mappings are copied over */ 4469 (*M)->rmap->bs = mat->rmap->bs; 4470 (*M)->cmap->bs = mat->cmap->bs; 4471 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4472 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4473 (*M)->rmap->mapping = mat->rmap->mapping; 4474 (*M)->cmap->mapping = mat->cmap->mapping; 4475 } 4476 (*M)->stencil.dim = mat->stencil.dim; 4477 (*M)->stencil.noc = mat->stencil.noc; 4478 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4479 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4480 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4481 } 4482 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4483 } 4484 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4485 4486 /* Copy Mat options */ 4487 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4488 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4489 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4490 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4491 PetscFunctionReturn(PETSC_SUCCESS); 4492 } 4493 4494 /*@C 4495 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4496 4497 Not Collective 4498 4499 Input Parameter: 4500 . mat - the matrix, must be a factored matrix 4501 4502 Output Parameter: 4503 . type - the string name of the package (do not free this string) 4504 4505 Level: intermediate 4506 4507 Fortran Note: 4508 Pass in an empty string that is long enough and the package name will be copied into it. 4509 4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4511 @*/ 4512 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4513 { 4514 PetscErrorCode (*conv)(Mat, MatSolverType *); 4515 4516 PetscFunctionBegin; 4517 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4518 PetscValidType(mat, 1); 4519 PetscAssertPointer(type, 2); 4520 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4521 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4522 if (conv) PetscCall((*conv)(mat, type)); 4523 else *type = MATSOLVERPETSC; 4524 PetscFunctionReturn(PETSC_SUCCESS); 4525 } 4526 4527 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4528 struct _MatSolverTypeForSpecifcType { 4529 MatType mtype; 4530 /* no entry for MAT_FACTOR_NONE */ 4531 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4532 MatSolverTypeForSpecifcType next; 4533 }; 4534 4535 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4536 struct _MatSolverTypeHolder { 4537 char *name; 4538 MatSolverTypeForSpecifcType handlers; 4539 MatSolverTypeHolder next; 4540 }; 4541 4542 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4543 4544 /*@C 4545 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4546 4547 Logically Collective, No Fortran Support 4548 4549 Input Parameters: 4550 + package - name of the package, for example petsc or superlu 4551 . mtype - the matrix type that works with this package 4552 . ftype - the type of factorization supported by the package 4553 - createfactor - routine that will create the factored matrix ready to be used 4554 4555 Level: developer 4556 4557 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4558 `MatGetFactor()` 4559 @*/ 4560 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4561 { 4562 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4563 PetscBool flg; 4564 MatSolverTypeForSpecifcType inext, iprev = NULL; 4565 4566 PetscFunctionBegin; 4567 PetscCall(MatInitializePackage()); 4568 if (!next) { 4569 PetscCall(PetscNew(&MatSolverTypeHolders)); 4570 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4571 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4572 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4573 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4574 PetscFunctionReturn(PETSC_SUCCESS); 4575 } 4576 while (next) { 4577 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4578 if (flg) { 4579 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4580 inext = next->handlers; 4581 while (inext) { 4582 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4583 if (flg) { 4584 inext->createfactor[(int)ftype - 1] = createfactor; 4585 PetscFunctionReturn(PETSC_SUCCESS); 4586 } 4587 iprev = inext; 4588 inext = inext->next; 4589 } 4590 PetscCall(PetscNew(&iprev->next)); 4591 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4592 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4593 PetscFunctionReturn(PETSC_SUCCESS); 4594 } 4595 prev = next; 4596 next = next->next; 4597 } 4598 PetscCall(PetscNew(&prev->next)); 4599 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4600 PetscCall(PetscNew(&prev->next->handlers)); 4601 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4602 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4603 PetscFunctionReturn(PETSC_SUCCESS); 4604 } 4605 4606 /*@C 4607 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4608 4609 Input Parameters: 4610 + 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 4611 . ftype - the type of factorization supported by the type 4612 - mtype - the matrix type that works with this type 4613 4614 Output Parameters: 4615 + foundtype - `PETSC_TRUE` if the type was registered 4616 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4617 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4618 4619 Calling sequence of `createfactor`: 4620 + A - the matrix providing the factor matrix 4621 . mtype - the `MatType` of the factor requested 4622 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4623 4624 Level: developer 4625 4626 Note: 4627 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4628 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4629 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4630 4631 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4632 `MatInitializePackage()` 4633 @*/ 4634 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4635 { 4636 MatSolverTypeHolder next = MatSolverTypeHolders; 4637 PetscBool flg; 4638 MatSolverTypeForSpecifcType inext; 4639 4640 PetscFunctionBegin; 4641 if (foundtype) *foundtype = PETSC_FALSE; 4642 if (foundmtype) *foundmtype = PETSC_FALSE; 4643 if (createfactor) *createfactor = NULL; 4644 4645 if (type) { 4646 while (next) { 4647 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4648 if (flg) { 4649 if (foundtype) *foundtype = PETSC_TRUE; 4650 inext = next->handlers; 4651 while (inext) { 4652 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4653 if (flg) { 4654 if (foundmtype) *foundmtype = PETSC_TRUE; 4655 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4656 PetscFunctionReturn(PETSC_SUCCESS); 4657 } 4658 inext = inext->next; 4659 } 4660 } 4661 next = next->next; 4662 } 4663 } else { 4664 while (next) { 4665 inext = next->handlers; 4666 while (inext) { 4667 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4668 if (flg && inext->createfactor[(int)ftype - 1]) { 4669 if (foundtype) *foundtype = PETSC_TRUE; 4670 if (foundmtype) *foundmtype = PETSC_TRUE; 4671 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4672 PetscFunctionReturn(PETSC_SUCCESS); 4673 } 4674 inext = inext->next; 4675 } 4676 next = next->next; 4677 } 4678 /* try with base classes inext->mtype */ 4679 next = MatSolverTypeHolders; 4680 while (next) { 4681 inext = next->handlers; 4682 while (inext) { 4683 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4684 if (flg && inext->createfactor[(int)ftype - 1]) { 4685 if (foundtype) *foundtype = PETSC_TRUE; 4686 if (foundmtype) *foundmtype = PETSC_TRUE; 4687 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4688 PetscFunctionReturn(PETSC_SUCCESS); 4689 } 4690 inext = inext->next; 4691 } 4692 next = next->next; 4693 } 4694 } 4695 PetscFunctionReturn(PETSC_SUCCESS); 4696 } 4697 4698 PetscErrorCode MatSolverTypeDestroy(void) 4699 { 4700 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4701 MatSolverTypeForSpecifcType inext, iprev; 4702 4703 PetscFunctionBegin; 4704 while (next) { 4705 PetscCall(PetscFree(next->name)); 4706 inext = next->handlers; 4707 while (inext) { 4708 PetscCall(PetscFree(inext->mtype)); 4709 iprev = inext; 4710 inext = inext->next; 4711 PetscCall(PetscFree(iprev)); 4712 } 4713 prev = next; 4714 next = next->next; 4715 PetscCall(PetscFree(prev)); 4716 } 4717 MatSolverTypeHolders = NULL; 4718 PetscFunctionReturn(PETSC_SUCCESS); 4719 } 4720 4721 /*@ 4722 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4723 4724 Logically Collective 4725 4726 Input Parameter: 4727 . mat - the matrix 4728 4729 Output Parameter: 4730 . flg - `PETSC_TRUE` if uses the ordering 4731 4732 Level: developer 4733 4734 Note: 4735 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4736 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4737 4738 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4739 @*/ 4740 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4741 { 4742 PetscFunctionBegin; 4743 *flg = mat->canuseordering; 4744 PetscFunctionReturn(PETSC_SUCCESS); 4745 } 4746 4747 /*@ 4748 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4749 4750 Logically Collective 4751 4752 Input Parameters: 4753 + mat - the matrix obtained with `MatGetFactor()` 4754 - ftype - the factorization type to be used 4755 4756 Output Parameter: 4757 . otype - the preferred ordering type 4758 4759 Level: developer 4760 4761 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4762 @*/ 4763 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4764 { 4765 PetscFunctionBegin; 4766 *otype = mat->preferredordering[ftype]; 4767 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4768 PetscFunctionReturn(PETSC_SUCCESS); 4769 } 4770 4771 /*@ 4772 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4773 4774 Collective 4775 4776 Input Parameters: 4777 + mat - the matrix 4778 . 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 4779 the other criteria is returned 4780 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4781 4782 Output Parameter: 4783 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4784 4785 Options Database Keys: 4786 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4787 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4788 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4789 4790 Level: intermediate 4791 4792 Notes: 4793 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4794 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4795 4796 Users usually access the factorization solvers via `KSP` 4797 4798 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4799 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 4800 4801 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4802 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4803 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4804 4805 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4806 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4807 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4808 4809 Developer Note: 4810 This should actually be called `MatCreateFactor()` since it creates a new factor object 4811 4812 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4813 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4814 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4815 @*/ 4816 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4817 { 4818 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4819 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4820 4821 PetscFunctionBegin; 4822 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4823 PetscValidType(mat, 1); 4824 4825 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4826 MatCheckPreallocated(mat, 1); 4827 4828 PetscCall(MatIsShell(mat, &shell)); 4829 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4830 if (hasop) { 4831 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4832 PetscFunctionReturn(PETSC_SUCCESS); 4833 } 4834 4835 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4836 if (!foundtype) { 4837 if (type) { 4838 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], 4839 ((PetscObject)mat)->type_name, type); 4840 } else { 4841 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); 4842 } 4843 } 4844 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4845 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); 4846 4847 PetscCall((*conv)(mat, ftype, f)); 4848 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4849 PetscFunctionReturn(PETSC_SUCCESS); 4850 } 4851 4852 /*@ 4853 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4854 4855 Not Collective 4856 4857 Input Parameters: 4858 + mat - the matrix 4859 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4860 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4861 4862 Output Parameter: 4863 . flg - PETSC_TRUE if the factorization is available 4864 4865 Level: intermediate 4866 4867 Notes: 4868 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4869 such as pastix, superlu, mumps etc. 4870 4871 PETSc must have been ./configure to use the external solver, using the option --download-package 4872 4873 Developer Note: 4874 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4875 4876 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4877 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4878 @*/ 4879 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4880 { 4881 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4882 4883 PetscFunctionBegin; 4884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4885 PetscAssertPointer(flg, 4); 4886 4887 *flg = PETSC_FALSE; 4888 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4889 4890 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4891 MatCheckPreallocated(mat, 1); 4892 4893 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4894 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4895 PetscFunctionReturn(PETSC_SUCCESS); 4896 } 4897 4898 /*@ 4899 MatDuplicate - Duplicates a matrix including the non-zero structure. 4900 4901 Collective 4902 4903 Input Parameters: 4904 + mat - the matrix 4905 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4906 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4907 4908 Output Parameter: 4909 . M - pointer to place new matrix 4910 4911 Level: intermediate 4912 4913 Notes: 4914 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4915 4916 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4917 4918 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. 4919 4920 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4921 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4922 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4923 4924 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4925 @*/ 4926 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4927 { 4928 Mat B; 4929 VecType vtype; 4930 PetscInt i; 4931 PetscObject dm, container_h, container_d; 4932 void (*viewf)(void); 4933 4934 PetscFunctionBegin; 4935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4936 PetscValidType(mat, 1); 4937 PetscAssertPointer(M, 3); 4938 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4939 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4940 MatCheckPreallocated(mat, 1); 4941 4942 *M = NULL; 4943 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4944 PetscUseTypeMethod(mat, duplicate, op, M); 4945 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4946 B = *M; 4947 4948 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4949 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4950 PetscCall(MatGetVecType(mat, &vtype)); 4951 PetscCall(MatSetVecType(B, vtype)); 4952 4953 B->stencil.dim = mat->stencil.dim; 4954 B->stencil.noc = mat->stencil.noc; 4955 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4956 B->stencil.dims[i] = mat->stencil.dims[i]; 4957 B->stencil.starts[i] = mat->stencil.starts[i]; 4958 } 4959 4960 B->nooffproczerorows = mat->nooffproczerorows; 4961 B->nooffprocentries = mat->nooffprocentries; 4962 4963 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4964 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4965 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4966 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4967 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4968 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4969 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4970 PetscFunctionReturn(PETSC_SUCCESS); 4971 } 4972 4973 /*@ 4974 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4975 4976 Logically Collective 4977 4978 Input Parameter: 4979 . mat - the matrix 4980 4981 Output Parameter: 4982 . v - the diagonal of the matrix 4983 4984 Level: intermediate 4985 4986 Note: 4987 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4988 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4989 is larger than `ndiag`, the values of the remaining entries are unspecified. 4990 4991 Currently only correct in parallel for square matrices. 4992 4993 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4994 @*/ 4995 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4996 { 4997 PetscFunctionBegin; 4998 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4999 PetscValidType(mat, 1); 5000 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5001 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5002 MatCheckPreallocated(mat, 1); 5003 if (PetscDefined(USE_DEBUG)) { 5004 PetscInt nv, row, col, ndiag; 5005 5006 PetscCall(VecGetLocalSize(v, &nv)); 5007 PetscCall(MatGetLocalSize(mat, &row, &col)); 5008 ndiag = PetscMin(row, col); 5009 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); 5010 } 5011 5012 PetscUseTypeMethod(mat, getdiagonal, v); 5013 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5014 PetscFunctionReturn(PETSC_SUCCESS); 5015 } 5016 5017 /*@ 5018 MatGetRowMin - Gets the minimum value (of the real part) of each 5019 row of the matrix 5020 5021 Logically Collective 5022 5023 Input Parameter: 5024 . mat - the matrix 5025 5026 Output Parameters: 5027 + v - the vector for storing the maximums 5028 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5029 5030 Level: intermediate 5031 5032 Note: 5033 The result of this call are the same as if one converted the matrix to dense format 5034 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5035 5036 This code is only implemented for a couple of matrix formats. 5037 5038 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5039 `MatGetRowMax()` 5040 @*/ 5041 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5042 { 5043 PetscFunctionBegin; 5044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5045 PetscValidType(mat, 1); 5046 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5047 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5048 5049 if (!mat->cmap->N) { 5050 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5051 if (idx) { 5052 PetscInt i, m = mat->rmap->n; 5053 for (i = 0; i < m; i++) idx[i] = -1; 5054 } 5055 } else { 5056 MatCheckPreallocated(mat, 1); 5057 } 5058 PetscUseTypeMethod(mat, getrowmin, v, idx); 5059 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5060 PetscFunctionReturn(PETSC_SUCCESS); 5061 } 5062 5063 /*@ 5064 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5065 row of the matrix 5066 5067 Logically Collective 5068 5069 Input Parameter: 5070 . mat - the matrix 5071 5072 Output Parameters: 5073 + v - the vector for storing the minimums 5074 - idx - the indices of the column found for each row (or `NULL` if not needed) 5075 5076 Level: intermediate 5077 5078 Notes: 5079 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5080 row is 0 (the first column). 5081 5082 This code is only implemented for a couple of matrix formats. 5083 5084 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5085 @*/ 5086 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5087 { 5088 PetscFunctionBegin; 5089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5090 PetscValidType(mat, 1); 5091 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5092 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5093 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5094 5095 if (!mat->cmap->N) { 5096 PetscCall(VecSet(v, 0.0)); 5097 if (idx) { 5098 PetscInt i, m = mat->rmap->n; 5099 for (i = 0; i < m; i++) idx[i] = -1; 5100 } 5101 } else { 5102 MatCheckPreallocated(mat, 1); 5103 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5104 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5105 } 5106 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5107 PetscFunctionReturn(PETSC_SUCCESS); 5108 } 5109 5110 /*@ 5111 MatGetRowMax - Gets the maximum value (of the real part) of each 5112 row of the matrix 5113 5114 Logically Collective 5115 5116 Input Parameter: 5117 . mat - the matrix 5118 5119 Output Parameters: 5120 + v - the vector for storing the maximums 5121 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5122 5123 Level: intermediate 5124 5125 Notes: 5126 The result of this call are the same as if one converted the matrix to dense format 5127 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5128 5129 This code is only implemented for a couple of matrix formats. 5130 5131 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5132 @*/ 5133 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5134 { 5135 PetscFunctionBegin; 5136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5137 PetscValidType(mat, 1); 5138 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5139 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5140 5141 if (!mat->cmap->N) { 5142 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5143 if (idx) { 5144 PetscInt i, m = mat->rmap->n; 5145 for (i = 0; i < m; i++) idx[i] = -1; 5146 } 5147 } else { 5148 MatCheckPreallocated(mat, 1); 5149 PetscUseTypeMethod(mat, getrowmax, v, idx); 5150 } 5151 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5152 PetscFunctionReturn(PETSC_SUCCESS); 5153 } 5154 5155 /*@ 5156 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5157 row of the matrix 5158 5159 Logically Collective 5160 5161 Input Parameter: 5162 . mat - the matrix 5163 5164 Output Parameters: 5165 + v - the vector for storing the maximums 5166 - idx - the indices of the column found for each row (or `NULL` if not needed) 5167 5168 Level: intermediate 5169 5170 Notes: 5171 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5172 row is 0 (the first column). 5173 5174 This code is only implemented for a couple of matrix formats. 5175 5176 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5177 @*/ 5178 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5179 { 5180 PetscFunctionBegin; 5181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5182 PetscValidType(mat, 1); 5183 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5184 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5185 5186 if (!mat->cmap->N) { 5187 PetscCall(VecSet(v, 0.0)); 5188 if (idx) { 5189 PetscInt i, m = mat->rmap->n; 5190 for (i = 0; i < m; i++) idx[i] = -1; 5191 } 5192 } else { 5193 MatCheckPreallocated(mat, 1); 5194 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5195 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5196 } 5197 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5198 PetscFunctionReturn(PETSC_SUCCESS); 5199 } 5200 5201 /*@ 5202 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5203 5204 Logically Collective 5205 5206 Input Parameter: 5207 . mat - the matrix 5208 5209 Output Parameter: 5210 . v - the vector for storing the sum 5211 5212 Level: intermediate 5213 5214 This code is only implemented for a couple of matrix formats. 5215 5216 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5217 @*/ 5218 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5219 { 5220 PetscFunctionBegin; 5221 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5222 PetscValidType(mat, 1); 5223 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5224 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5225 5226 if (!mat->cmap->N) { 5227 PetscCall(VecSet(v, 0.0)); 5228 } else { 5229 MatCheckPreallocated(mat, 1); 5230 PetscUseTypeMethod(mat, getrowsumabs, v); 5231 } 5232 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5233 PetscFunctionReturn(PETSC_SUCCESS); 5234 } 5235 5236 /*@ 5237 MatGetRowSum - Gets the sum of each row of the matrix 5238 5239 Logically or Neighborhood Collective 5240 5241 Input Parameter: 5242 . mat - the matrix 5243 5244 Output Parameter: 5245 . v - the vector for storing the sum of rows 5246 5247 Level: intermediate 5248 5249 Note: 5250 This code is slow since it is not currently specialized for different formats 5251 5252 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5253 @*/ 5254 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5255 { 5256 Vec ones; 5257 5258 PetscFunctionBegin; 5259 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5260 PetscValidType(mat, 1); 5261 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5262 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5263 MatCheckPreallocated(mat, 1); 5264 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5265 PetscCall(VecSet(ones, 1.)); 5266 PetscCall(MatMult(mat, ones, v)); 5267 PetscCall(VecDestroy(&ones)); 5268 PetscFunctionReturn(PETSC_SUCCESS); 5269 } 5270 5271 /*@ 5272 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5273 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5274 5275 Collective 5276 5277 Input Parameter: 5278 . mat - the matrix to provide the transpose 5279 5280 Output Parameter: 5281 . 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 5282 5283 Level: advanced 5284 5285 Note: 5286 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 5287 routine allows bypassing that call. 5288 5289 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5290 @*/ 5291 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5292 { 5293 PetscContainer rB = NULL; 5294 MatParentState *rb = NULL; 5295 5296 PetscFunctionBegin; 5297 PetscCall(PetscNew(&rb)); 5298 rb->id = ((PetscObject)mat)->id; 5299 rb->state = 0; 5300 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5301 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5302 PetscCall(PetscContainerSetPointer(rB, rb)); 5303 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5304 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5305 PetscCall(PetscObjectDereference((PetscObject)rB)); 5306 PetscFunctionReturn(PETSC_SUCCESS); 5307 } 5308 5309 /*@ 5310 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5311 5312 Collective 5313 5314 Input Parameters: 5315 + mat - the matrix to transpose 5316 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5317 5318 Output Parameter: 5319 . B - the transpose 5320 5321 Level: intermediate 5322 5323 Notes: 5324 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5325 5326 `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 5327 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5328 5329 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. 5330 5331 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5332 5333 If mat is unchanged from the last call this function returns immediately without recomputing the result 5334 5335 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5336 5337 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5338 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5339 @*/ 5340 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5341 { 5342 PetscContainer rB = NULL; 5343 MatParentState *rb = NULL; 5344 5345 PetscFunctionBegin; 5346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5347 PetscValidType(mat, 1); 5348 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5349 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5350 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5351 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5352 MatCheckPreallocated(mat, 1); 5353 if (reuse == MAT_REUSE_MATRIX) { 5354 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5355 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5356 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5357 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5358 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5359 } 5360 5361 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5362 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5363 PetscUseTypeMethod(mat, transpose, reuse, B); 5364 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5365 } 5366 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5367 5368 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5369 if (reuse != MAT_INPLACE_MATRIX) { 5370 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5371 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5372 rb->state = ((PetscObject)mat)->state; 5373 rb->nonzerostate = mat->nonzerostate; 5374 } 5375 PetscFunctionReturn(PETSC_SUCCESS); 5376 } 5377 5378 /*@ 5379 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5380 5381 Collective 5382 5383 Input Parameter: 5384 . A - the matrix to transpose 5385 5386 Output Parameter: 5387 . 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 5388 numerical portion. 5389 5390 Level: intermediate 5391 5392 Note: 5393 This is not supported for many matrix types, use `MatTranspose()` in those cases 5394 5395 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5396 @*/ 5397 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5398 { 5399 PetscFunctionBegin; 5400 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5401 PetscValidType(A, 1); 5402 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5403 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5404 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5405 PetscUseTypeMethod(A, transposesymbolic, B); 5406 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5407 5408 PetscCall(MatTransposeSetPrecursor(A, *B)); 5409 PetscFunctionReturn(PETSC_SUCCESS); 5410 } 5411 5412 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5413 { 5414 PetscContainer rB; 5415 MatParentState *rb; 5416 5417 PetscFunctionBegin; 5418 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5419 PetscValidType(A, 1); 5420 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5421 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5422 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5423 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5424 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5425 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5426 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5427 PetscFunctionReturn(PETSC_SUCCESS); 5428 } 5429 5430 /*@ 5431 MatIsTranspose - Test whether a matrix is another one's transpose, 5432 or its own, in which case it tests symmetry. 5433 5434 Collective 5435 5436 Input Parameters: 5437 + A - the matrix to test 5438 . B - the matrix to test against, this can equal the first parameter 5439 - tol - tolerance, differences between entries smaller than this are counted as zero 5440 5441 Output Parameter: 5442 . flg - the result 5443 5444 Level: intermediate 5445 5446 Notes: 5447 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5448 test involves parallel copies of the block off-diagonal parts of the matrix. 5449 5450 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5451 @*/ 5452 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5453 { 5454 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5455 5456 PetscFunctionBegin; 5457 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5458 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5459 PetscAssertPointer(flg, 4); 5460 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5461 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5462 *flg = PETSC_FALSE; 5463 if (f && g) { 5464 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5465 PetscCall((*f)(A, B, tol, flg)); 5466 } else { 5467 MatType mattype; 5468 5469 PetscCall(MatGetType(f ? B : A, &mattype)); 5470 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5471 } 5472 PetscFunctionReturn(PETSC_SUCCESS); 5473 } 5474 5475 /*@ 5476 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5477 5478 Collective 5479 5480 Input Parameters: 5481 + mat - the matrix to transpose and complex conjugate 5482 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5483 5484 Output Parameter: 5485 . B - the Hermitian transpose 5486 5487 Level: intermediate 5488 5489 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5490 @*/ 5491 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5492 { 5493 PetscFunctionBegin; 5494 PetscCall(MatTranspose(mat, reuse, B)); 5495 #if defined(PETSC_USE_COMPLEX) 5496 PetscCall(MatConjugate(*B)); 5497 #endif 5498 PetscFunctionReturn(PETSC_SUCCESS); 5499 } 5500 5501 /*@ 5502 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5503 5504 Collective 5505 5506 Input Parameters: 5507 + A - the matrix to test 5508 . B - the matrix to test against, this can equal the first parameter 5509 - tol - tolerance, differences between entries smaller than this are counted as zero 5510 5511 Output Parameter: 5512 . flg - the result 5513 5514 Level: intermediate 5515 5516 Notes: 5517 Only available for `MATAIJ` matrices. 5518 5519 The sequential algorithm 5520 has a running time of the order of the number of nonzeros; the parallel 5521 test involves parallel copies of the block off-diagonal parts of the matrix. 5522 5523 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5524 @*/ 5525 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5526 { 5527 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5528 5529 PetscFunctionBegin; 5530 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5531 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5532 PetscAssertPointer(flg, 4); 5533 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5534 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5535 if (f && g) { 5536 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5537 PetscCall((*f)(A, B, tol, flg)); 5538 } 5539 PetscFunctionReturn(PETSC_SUCCESS); 5540 } 5541 5542 /*@ 5543 MatPermute - Creates a new matrix with rows and columns permuted from the 5544 original. 5545 5546 Collective 5547 5548 Input Parameters: 5549 + mat - the matrix to permute 5550 . row - row permutation, each processor supplies only the permutation for its rows 5551 - col - column permutation, each processor supplies only the permutation for its columns 5552 5553 Output Parameter: 5554 . B - the permuted matrix 5555 5556 Level: advanced 5557 5558 Note: 5559 The index sets map from row/col of permuted matrix to row/col of original matrix. 5560 The index sets should be on the same communicator as mat and have the same local sizes. 5561 5562 Developer Note: 5563 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5564 exploit the fact that row and col are permutations, consider implementing the 5565 more general `MatCreateSubMatrix()` instead. 5566 5567 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5568 @*/ 5569 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5570 { 5571 PetscFunctionBegin; 5572 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5573 PetscValidType(mat, 1); 5574 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5575 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5576 PetscAssertPointer(B, 4); 5577 PetscCheckSameComm(mat, 1, row, 2); 5578 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5579 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5580 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5581 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5582 MatCheckPreallocated(mat, 1); 5583 5584 if (mat->ops->permute) { 5585 PetscUseTypeMethod(mat, permute, row, col, B); 5586 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5587 } else { 5588 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5589 } 5590 PetscFunctionReturn(PETSC_SUCCESS); 5591 } 5592 5593 /*@ 5594 MatEqual - Compares two matrices. 5595 5596 Collective 5597 5598 Input Parameters: 5599 + A - the first matrix 5600 - B - the second matrix 5601 5602 Output Parameter: 5603 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5604 5605 Level: intermediate 5606 5607 .seealso: [](ch_matrices), `Mat` 5608 @*/ 5609 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5610 { 5611 PetscFunctionBegin; 5612 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5613 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5614 PetscValidType(A, 1); 5615 PetscValidType(B, 2); 5616 PetscAssertPointer(flg, 3); 5617 PetscCheckSameComm(A, 1, B, 2); 5618 MatCheckPreallocated(A, 1); 5619 MatCheckPreallocated(B, 2); 5620 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5621 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5622 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, 5623 B->cmap->N); 5624 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5625 PetscUseTypeMethod(A, equal, B, flg); 5626 } else { 5627 PetscCall(MatMultEqual(A, B, 10, flg)); 5628 } 5629 PetscFunctionReturn(PETSC_SUCCESS); 5630 } 5631 5632 /*@ 5633 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5634 matrices that are stored as vectors. Either of the two scaling 5635 matrices can be `NULL`. 5636 5637 Collective 5638 5639 Input Parameters: 5640 + mat - the matrix to be scaled 5641 . l - the left scaling vector (or `NULL`) 5642 - r - the right scaling vector (or `NULL`) 5643 5644 Level: intermediate 5645 5646 Note: 5647 `MatDiagonalScale()` computes $A = LAR$, where 5648 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5649 The L scales the rows of the matrix, the R scales the columns of the matrix. 5650 5651 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5652 @*/ 5653 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5654 { 5655 PetscFunctionBegin; 5656 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5657 PetscValidType(mat, 1); 5658 if (l) { 5659 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5660 PetscCheckSameComm(mat, 1, l, 2); 5661 } 5662 if (r) { 5663 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5664 PetscCheckSameComm(mat, 1, r, 3); 5665 } 5666 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5667 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5668 MatCheckPreallocated(mat, 1); 5669 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5670 5671 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5672 PetscUseTypeMethod(mat, diagonalscale, l, r); 5673 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5674 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5675 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5676 PetscFunctionReturn(PETSC_SUCCESS); 5677 } 5678 5679 /*@ 5680 MatScale - Scales all elements of a matrix by a given number. 5681 5682 Logically Collective 5683 5684 Input Parameters: 5685 + mat - the matrix to be scaled 5686 - a - the scaling value 5687 5688 Level: intermediate 5689 5690 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5691 @*/ 5692 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5693 { 5694 PetscFunctionBegin; 5695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5696 PetscValidType(mat, 1); 5697 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5698 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5699 PetscValidLogicalCollectiveScalar(mat, a, 2); 5700 MatCheckPreallocated(mat, 1); 5701 5702 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5703 if (a != (PetscScalar)1.0) { 5704 PetscUseTypeMethod(mat, scale, a); 5705 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5706 } 5707 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5708 PetscFunctionReturn(PETSC_SUCCESS); 5709 } 5710 5711 /*@ 5712 MatNorm - Calculates various norms of a matrix. 5713 5714 Collective 5715 5716 Input Parameters: 5717 + mat - the matrix 5718 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5719 5720 Output Parameter: 5721 . nrm - the resulting norm 5722 5723 Level: intermediate 5724 5725 .seealso: [](ch_matrices), `Mat` 5726 @*/ 5727 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5728 { 5729 PetscFunctionBegin; 5730 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5731 PetscValidType(mat, 1); 5732 PetscAssertPointer(nrm, 3); 5733 5734 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5735 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5736 MatCheckPreallocated(mat, 1); 5737 5738 PetscUseTypeMethod(mat, norm, type, nrm); 5739 PetscFunctionReturn(PETSC_SUCCESS); 5740 } 5741 5742 /* 5743 This variable is used to prevent counting of MatAssemblyBegin() that 5744 are called from within a MatAssemblyEnd(). 5745 */ 5746 static PetscInt MatAssemblyEnd_InUse = 0; 5747 /*@ 5748 MatAssemblyBegin - Begins assembling the matrix. This routine should 5749 be called after completing all calls to `MatSetValues()`. 5750 5751 Collective 5752 5753 Input Parameters: 5754 + mat - the matrix 5755 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5756 5757 Level: beginner 5758 5759 Notes: 5760 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5761 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5762 5763 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5764 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5765 using the matrix. 5766 5767 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5768 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 5769 a global collective operation requiring all processes that share the matrix. 5770 5771 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5772 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5773 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5774 5775 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5776 @*/ 5777 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5778 { 5779 PetscFunctionBegin; 5780 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5781 PetscValidType(mat, 1); 5782 MatCheckPreallocated(mat, 1); 5783 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5784 if (mat->assembled) { 5785 mat->was_assembled = PETSC_TRUE; 5786 mat->assembled = PETSC_FALSE; 5787 } 5788 5789 if (!MatAssemblyEnd_InUse) { 5790 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5791 PetscTryTypeMethod(mat, assemblybegin, type); 5792 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5793 } else PetscTryTypeMethod(mat, assemblybegin, type); 5794 PetscFunctionReturn(PETSC_SUCCESS); 5795 } 5796 5797 /*@ 5798 MatAssembled - Indicates if a matrix has been assembled and is ready for 5799 use; for example, in matrix-vector product. 5800 5801 Not Collective 5802 5803 Input Parameter: 5804 . mat - the matrix 5805 5806 Output Parameter: 5807 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5808 5809 Level: advanced 5810 5811 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5812 @*/ 5813 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5814 { 5815 PetscFunctionBegin; 5816 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5817 PetscAssertPointer(assembled, 2); 5818 *assembled = mat->assembled; 5819 PetscFunctionReturn(PETSC_SUCCESS); 5820 } 5821 5822 /*@ 5823 MatAssemblyEnd - Completes assembling the matrix. This routine should 5824 be called after `MatAssemblyBegin()`. 5825 5826 Collective 5827 5828 Input Parameters: 5829 + mat - the matrix 5830 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5831 5832 Options Database Keys: 5833 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5834 . -mat_view ::ascii_info_detail - Prints more detailed info 5835 . -mat_view - Prints matrix in ASCII format 5836 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5837 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5838 . -display <name> - Sets display name (default is host) 5839 . -draw_pause <sec> - Sets number of seconds to pause after display 5840 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5841 . -viewer_socket_machine <machine> - Machine to use for socket 5842 . -viewer_socket_port <port> - Port number to use for socket 5843 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5844 5845 Level: beginner 5846 5847 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5848 @*/ 5849 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5850 { 5851 static PetscInt inassm = 0; 5852 PetscBool flg = PETSC_FALSE; 5853 5854 PetscFunctionBegin; 5855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5856 PetscValidType(mat, 1); 5857 5858 inassm++; 5859 MatAssemblyEnd_InUse++; 5860 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5861 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5862 PetscTryTypeMethod(mat, assemblyend, type); 5863 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5864 } else PetscTryTypeMethod(mat, assemblyend, type); 5865 5866 /* Flush assembly is not a true assembly */ 5867 if (type != MAT_FLUSH_ASSEMBLY) { 5868 if (mat->num_ass) { 5869 if (!mat->symmetry_eternal) { 5870 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5871 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5872 } 5873 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5874 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5875 } 5876 mat->num_ass++; 5877 mat->assembled = PETSC_TRUE; 5878 mat->ass_nonzerostate = mat->nonzerostate; 5879 } 5880 5881 mat->insertmode = NOT_SET_VALUES; 5882 MatAssemblyEnd_InUse--; 5883 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5884 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5885 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5886 5887 if (mat->checksymmetryonassembly) { 5888 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5889 if (flg) { 5890 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5891 } else { 5892 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5893 } 5894 } 5895 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5896 } 5897 inassm--; 5898 PetscFunctionReturn(PETSC_SUCCESS); 5899 } 5900 5901 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5902 /*@ 5903 MatSetOption - Sets a parameter option for a matrix. Some options 5904 may be specific to certain storage formats. Some options 5905 determine how values will be inserted (or added). Sorted, 5906 row-oriented input will generally assemble the fastest. The default 5907 is row-oriented. 5908 5909 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5910 5911 Input Parameters: 5912 + mat - the matrix 5913 . op - the option, one of those listed below (and possibly others), 5914 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5915 5916 Options Describing Matrix Structure: 5917 + `MAT_SPD` - symmetric positive definite 5918 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5919 . `MAT_HERMITIAN` - transpose is the complex conjugation 5920 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5921 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5922 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5923 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5924 5925 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5926 do not need to be computed (usually at a high cost) 5927 5928 Options For Use with `MatSetValues()`: 5929 Insert a logically dense subblock, which can be 5930 . `MAT_ROW_ORIENTED` - row-oriented (default) 5931 5932 These options reflect the data you pass in with `MatSetValues()`; it has 5933 nothing to do with how the data is stored internally in the matrix 5934 data structure. 5935 5936 When (re)assembling a matrix, we can restrict the input for 5937 efficiency/debugging purposes. These options include 5938 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5939 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5940 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5941 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5942 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5943 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5944 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5945 performance for very large process counts. 5946 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5947 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5948 functions, instead sending only neighbor messages. 5949 5950 Level: intermediate 5951 5952 Notes: 5953 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5954 5955 Some options are relevant only for particular matrix types and 5956 are thus ignored by others. Other options are not supported by 5957 certain matrix types and will generate an error message if set. 5958 5959 If using Fortran to compute a matrix, one may need to 5960 use the column-oriented option (or convert to the row-oriented 5961 format). 5962 5963 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5964 that would generate a new entry in the nonzero structure is instead 5965 ignored. Thus, if memory has not already been allocated for this particular 5966 data, then the insertion is ignored. For dense matrices, in which 5967 the entire array is allocated, no entries are ever ignored. 5968 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5969 5970 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5971 that would generate a new entry in the nonzero structure instead produces 5972 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 5973 5974 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5975 that would generate a new entry that has not been preallocated will 5976 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5977 only.) This is a useful flag when debugging matrix memory preallocation. 5978 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5979 5980 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5981 other processors should be dropped, rather than stashed. 5982 This is useful if you know that the "owning" processor is also 5983 always generating the correct matrix entries, so that PETSc need 5984 not transfer duplicate entries generated on another processor. 5985 5986 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5987 searches during matrix assembly. When this flag is set, the hash table 5988 is created during the first matrix assembly. This hash table is 5989 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5990 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5991 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5992 supported by `MATMPIBAIJ` format only. 5993 5994 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5995 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 5996 5997 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5998 a zero location in the matrix 5999 6000 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6001 6002 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6003 zero row routines and thus improves performance for very large process counts. 6004 6005 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6006 part of the matrix (since they should match the upper triangular part). 6007 6008 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6009 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6010 with finite difference schemes with non-periodic boundary conditions. 6011 6012 Developer Note: 6013 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6014 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6015 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6016 not changed. 6017 6018 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6019 @*/ 6020 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6021 { 6022 PetscFunctionBegin; 6023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6024 if (op > 0) { 6025 PetscValidLogicalCollectiveEnum(mat, op, 2); 6026 PetscValidLogicalCollectiveBool(mat, flg, 3); 6027 } 6028 6029 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); 6030 6031 switch (op) { 6032 case MAT_FORCE_DIAGONAL_ENTRIES: 6033 mat->force_diagonals = flg; 6034 PetscFunctionReturn(PETSC_SUCCESS); 6035 case MAT_NO_OFF_PROC_ENTRIES: 6036 mat->nooffprocentries = flg; 6037 PetscFunctionReturn(PETSC_SUCCESS); 6038 case MAT_SUBSET_OFF_PROC_ENTRIES: 6039 mat->assembly_subset = flg; 6040 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6041 #if !defined(PETSC_HAVE_MPIUNI) 6042 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6043 #endif 6044 mat->stash.first_assembly_done = PETSC_FALSE; 6045 } 6046 PetscFunctionReturn(PETSC_SUCCESS); 6047 case MAT_NO_OFF_PROC_ZERO_ROWS: 6048 mat->nooffproczerorows = flg; 6049 PetscFunctionReturn(PETSC_SUCCESS); 6050 case MAT_SPD: 6051 if (flg) { 6052 mat->spd = PETSC_BOOL3_TRUE; 6053 mat->symmetric = PETSC_BOOL3_TRUE; 6054 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6055 } else { 6056 mat->spd = PETSC_BOOL3_FALSE; 6057 } 6058 break; 6059 case MAT_SYMMETRIC: 6060 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6061 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6062 #if !defined(PETSC_USE_COMPLEX) 6063 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6064 #endif 6065 break; 6066 case MAT_HERMITIAN: 6067 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6068 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6069 #if !defined(PETSC_USE_COMPLEX) 6070 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6071 #endif 6072 break; 6073 case MAT_STRUCTURALLY_SYMMETRIC: 6074 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6075 break; 6076 case MAT_SYMMETRY_ETERNAL: 6077 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"); 6078 mat->symmetry_eternal = flg; 6079 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6080 break; 6081 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6082 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"); 6083 mat->structural_symmetry_eternal = flg; 6084 break; 6085 case MAT_SPD_ETERNAL: 6086 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"); 6087 mat->spd_eternal = flg; 6088 if (flg) { 6089 mat->structural_symmetry_eternal = PETSC_TRUE; 6090 mat->symmetry_eternal = PETSC_TRUE; 6091 } 6092 break; 6093 case MAT_STRUCTURE_ONLY: 6094 mat->structure_only = flg; 6095 break; 6096 case MAT_SORTED_FULL: 6097 mat->sortedfull = flg; 6098 break; 6099 default: 6100 break; 6101 } 6102 PetscTryTypeMethod(mat, setoption, op, flg); 6103 PetscFunctionReturn(PETSC_SUCCESS); 6104 } 6105 6106 /*@ 6107 MatGetOption - Gets a parameter option that has been set for a matrix. 6108 6109 Logically Collective 6110 6111 Input Parameters: 6112 + mat - the matrix 6113 - op - the option, this only responds to certain options, check the code for which ones 6114 6115 Output Parameter: 6116 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6117 6118 Level: intermediate 6119 6120 Notes: 6121 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6122 6123 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6124 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6125 6126 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6127 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6128 @*/ 6129 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6130 { 6131 PetscFunctionBegin; 6132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6133 PetscValidType(mat, 1); 6134 6135 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); 6136 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()"); 6137 6138 switch (op) { 6139 case MAT_NO_OFF_PROC_ENTRIES: 6140 *flg = mat->nooffprocentries; 6141 break; 6142 case MAT_NO_OFF_PROC_ZERO_ROWS: 6143 *flg = mat->nooffproczerorows; 6144 break; 6145 case MAT_SYMMETRIC: 6146 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6147 break; 6148 case MAT_HERMITIAN: 6149 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6150 break; 6151 case MAT_STRUCTURALLY_SYMMETRIC: 6152 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6153 break; 6154 case MAT_SPD: 6155 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6156 break; 6157 case MAT_SYMMETRY_ETERNAL: 6158 *flg = mat->symmetry_eternal; 6159 break; 6160 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6161 *flg = mat->symmetry_eternal; 6162 break; 6163 default: 6164 break; 6165 } 6166 PetscFunctionReturn(PETSC_SUCCESS); 6167 } 6168 6169 /*@ 6170 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6171 this routine retains the old nonzero structure. 6172 6173 Logically Collective 6174 6175 Input Parameter: 6176 . mat - the matrix 6177 6178 Level: intermediate 6179 6180 Note: 6181 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. 6182 See the Performance chapter of the users manual for information on preallocating matrices. 6183 6184 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6185 @*/ 6186 PetscErrorCode MatZeroEntries(Mat mat) 6187 { 6188 PetscFunctionBegin; 6189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6190 PetscValidType(mat, 1); 6191 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6192 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"); 6193 MatCheckPreallocated(mat, 1); 6194 6195 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6196 PetscUseTypeMethod(mat, zeroentries); 6197 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6198 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6199 PetscFunctionReturn(PETSC_SUCCESS); 6200 } 6201 6202 /*@ 6203 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6204 of a set of rows and columns of a matrix. 6205 6206 Collective 6207 6208 Input Parameters: 6209 + mat - the matrix 6210 . numRows - the number of rows/columns to zero 6211 . rows - the global row indices 6212 . diag - value put in the diagonal of the eliminated rows 6213 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6214 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6215 6216 Level: intermediate 6217 6218 Notes: 6219 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6220 6221 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6222 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 6223 6224 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6225 Krylov method to take advantage of the known solution on the zeroed rows. 6226 6227 For the parallel case, all processes that share the matrix (i.e., 6228 those in the communicator used for matrix creation) MUST call this 6229 routine, regardless of whether any rows being zeroed are owned by 6230 them. 6231 6232 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6233 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 6234 missing. 6235 6236 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6237 list only rows local to itself). 6238 6239 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6240 6241 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6242 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6243 @*/ 6244 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6245 { 6246 PetscFunctionBegin; 6247 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6248 PetscValidType(mat, 1); 6249 if (numRows) PetscAssertPointer(rows, 3); 6250 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6251 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6252 MatCheckPreallocated(mat, 1); 6253 6254 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6255 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6256 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6257 PetscFunctionReturn(PETSC_SUCCESS); 6258 } 6259 6260 /*@ 6261 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6262 of a set of rows and columns of a matrix. 6263 6264 Collective 6265 6266 Input Parameters: 6267 + mat - the matrix 6268 . is - the rows to zero 6269 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6270 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6271 - b - optional vector of right-hand side, that will be adjusted by provided solution 6272 6273 Level: intermediate 6274 6275 Note: 6276 See `MatZeroRowsColumns()` for details on how this routine operates. 6277 6278 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6279 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6280 @*/ 6281 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6282 { 6283 PetscInt numRows; 6284 const PetscInt *rows; 6285 6286 PetscFunctionBegin; 6287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6288 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6289 PetscValidType(mat, 1); 6290 PetscValidType(is, 2); 6291 PetscCall(ISGetLocalSize(is, &numRows)); 6292 PetscCall(ISGetIndices(is, &rows)); 6293 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6294 PetscCall(ISRestoreIndices(is, &rows)); 6295 PetscFunctionReturn(PETSC_SUCCESS); 6296 } 6297 6298 /*@ 6299 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6300 of a set of rows of a matrix. 6301 6302 Collective 6303 6304 Input Parameters: 6305 + mat - the matrix 6306 . numRows - the number of rows to zero 6307 . rows - the global row indices 6308 . diag - value put in the diagonal of the zeroed rows 6309 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6310 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6311 6312 Level: intermediate 6313 6314 Notes: 6315 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6316 6317 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6318 6319 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6320 Krylov method to take advantage of the known solution on the zeroed rows. 6321 6322 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) 6323 from the matrix. 6324 6325 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6326 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 6327 formats this does not alter the nonzero structure. 6328 6329 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6330 of the matrix is not changed the values are 6331 merely zeroed. 6332 6333 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6334 formats can optionally remove the main diagonal entry from the 6335 nonzero structure as well, by passing 0.0 as the final argument). 6336 6337 For the parallel case, all processes that share the matrix (i.e., 6338 those in the communicator used for matrix creation) MUST call this 6339 routine, regardless of whether any rows being zeroed are owned by 6340 them. 6341 6342 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6343 list only rows local to itself). 6344 6345 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6346 owns that are to be zeroed. This saves a global synchronization in the implementation. 6347 6348 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6349 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6350 @*/ 6351 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6352 { 6353 PetscFunctionBegin; 6354 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6355 PetscValidType(mat, 1); 6356 if (numRows) PetscAssertPointer(rows, 3); 6357 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6358 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6359 MatCheckPreallocated(mat, 1); 6360 6361 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6362 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6363 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6364 PetscFunctionReturn(PETSC_SUCCESS); 6365 } 6366 6367 /*@ 6368 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6369 of a set of rows of a matrix. 6370 6371 Collective 6372 6373 Input Parameters: 6374 + mat - the matrix 6375 . is - index set of rows to remove (if `NULL` then no row is removed) 6376 . diag - value put in all diagonals of eliminated rows 6377 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6378 - b - optional vector of right-hand side, that will be adjusted by provided solution 6379 6380 Level: intermediate 6381 6382 Note: 6383 See `MatZeroRows()` for details on how this routine operates. 6384 6385 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6386 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6387 @*/ 6388 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6389 { 6390 PetscInt numRows = 0; 6391 const PetscInt *rows = NULL; 6392 6393 PetscFunctionBegin; 6394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6395 PetscValidType(mat, 1); 6396 if (is) { 6397 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6398 PetscCall(ISGetLocalSize(is, &numRows)); 6399 PetscCall(ISGetIndices(is, &rows)); 6400 } 6401 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6402 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6403 PetscFunctionReturn(PETSC_SUCCESS); 6404 } 6405 6406 /*@ 6407 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6408 of a set of rows of a matrix. These rows must be local to the process. 6409 6410 Collective 6411 6412 Input Parameters: 6413 + mat - the matrix 6414 . numRows - the number of rows to remove 6415 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6416 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6417 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6418 - b - optional vector of right-hand side, that will be adjusted by provided solution 6419 6420 Level: intermediate 6421 6422 Notes: 6423 See `MatZeroRows()` for details on how this routine operates. 6424 6425 The grid coordinates are across the entire grid, not just the local portion 6426 6427 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6428 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6429 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6430 `DM_BOUNDARY_PERIODIC` boundary type. 6431 6432 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 6433 a single value per point) you can skip filling those indices. 6434 6435 Fortran Note: 6436 `idxm` and `idxn` should be declared as 6437 $ MatStencil idxm(4, m) 6438 and the values inserted using 6439 .vb 6440 idxm(MatStencil_i, 1) = i 6441 idxm(MatStencil_j, 1) = j 6442 idxm(MatStencil_k, 1) = k 6443 idxm(MatStencil_c, 1) = c 6444 etc 6445 .ve 6446 6447 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6448 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6449 @*/ 6450 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6451 { 6452 PetscInt dim = mat->stencil.dim; 6453 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6454 PetscInt *dims = mat->stencil.dims + 1; 6455 PetscInt *starts = mat->stencil.starts; 6456 PetscInt *dxm = (PetscInt *)rows; 6457 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6458 6459 PetscFunctionBegin; 6460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6461 PetscValidType(mat, 1); 6462 if (numRows) PetscAssertPointer(rows, 3); 6463 6464 PetscCall(PetscMalloc1(numRows, &jdxm)); 6465 for (i = 0; i < numRows; ++i) { 6466 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6467 for (j = 0; j < 3 - sdim; ++j) dxm++; 6468 /* Local index in X dir */ 6469 tmp = *dxm++ - starts[0]; 6470 /* Loop over remaining dimensions */ 6471 for (j = 0; j < dim - 1; ++j) { 6472 /* If nonlocal, set index to be negative */ 6473 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6474 /* Update local index */ 6475 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6476 } 6477 /* Skip component slot if necessary */ 6478 if (mat->stencil.noc) dxm++; 6479 /* Local row number */ 6480 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6481 } 6482 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6483 PetscCall(PetscFree(jdxm)); 6484 PetscFunctionReturn(PETSC_SUCCESS); 6485 } 6486 6487 /*@ 6488 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6489 of a set of rows and columns of a matrix. 6490 6491 Collective 6492 6493 Input Parameters: 6494 + mat - the matrix 6495 . numRows - the number of rows/columns to remove 6496 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6497 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6498 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6499 - b - optional vector of right-hand side, that will be adjusted by provided solution 6500 6501 Level: intermediate 6502 6503 Notes: 6504 See `MatZeroRowsColumns()` for details on how this routine operates. 6505 6506 The grid coordinates are across the entire grid, not just the local portion 6507 6508 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6509 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6510 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6511 `DM_BOUNDARY_PERIODIC` boundary type. 6512 6513 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 6514 a single value per point) you can skip filling those indices. 6515 6516 Fortran Note: 6517 `idxm` and `idxn` should be declared as 6518 $ MatStencil idxm(4, m) 6519 and the values inserted using 6520 .vb 6521 idxm(MatStencil_i, 1) = i 6522 idxm(MatStencil_j, 1) = j 6523 idxm(MatStencil_k, 1) = k 6524 idxm(MatStencil_c, 1) = c 6525 etc 6526 .ve 6527 6528 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6529 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6530 @*/ 6531 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6532 { 6533 PetscInt dim = mat->stencil.dim; 6534 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6535 PetscInt *dims = mat->stencil.dims + 1; 6536 PetscInt *starts = mat->stencil.starts; 6537 PetscInt *dxm = (PetscInt *)rows; 6538 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6539 6540 PetscFunctionBegin; 6541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6542 PetscValidType(mat, 1); 6543 if (numRows) PetscAssertPointer(rows, 3); 6544 6545 PetscCall(PetscMalloc1(numRows, &jdxm)); 6546 for (i = 0; i < numRows; ++i) { 6547 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6548 for (j = 0; j < 3 - sdim; ++j) dxm++; 6549 /* Local index in X dir */ 6550 tmp = *dxm++ - starts[0]; 6551 /* Loop over remaining dimensions */ 6552 for (j = 0; j < dim - 1; ++j) { 6553 /* If nonlocal, set index to be negative */ 6554 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6555 /* Update local index */ 6556 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6557 } 6558 /* Skip component slot if necessary */ 6559 if (mat->stencil.noc) dxm++; 6560 /* Local row number */ 6561 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6562 } 6563 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6564 PetscCall(PetscFree(jdxm)); 6565 PetscFunctionReturn(PETSC_SUCCESS); 6566 } 6567 6568 /*@C 6569 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6570 of a set of rows of a matrix; using local numbering of rows. 6571 6572 Collective 6573 6574 Input Parameters: 6575 + mat - the matrix 6576 . numRows - the number of rows to remove 6577 . rows - the local row indices 6578 . diag - value put in all diagonals of eliminated rows 6579 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6580 - b - optional vector of right-hand side, that will be adjusted by provided solution 6581 6582 Level: intermediate 6583 6584 Notes: 6585 Before calling `MatZeroRowsLocal()`, the user must first set the 6586 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6587 6588 See `MatZeroRows()` for details on how this routine operates. 6589 6590 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6591 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6592 @*/ 6593 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6594 { 6595 PetscFunctionBegin; 6596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6597 PetscValidType(mat, 1); 6598 if (numRows) PetscAssertPointer(rows, 3); 6599 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6600 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6601 MatCheckPreallocated(mat, 1); 6602 6603 if (mat->ops->zerorowslocal) { 6604 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6605 } else { 6606 IS is, newis; 6607 const PetscInt *newRows; 6608 6609 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6610 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6611 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6612 PetscCall(ISGetIndices(newis, &newRows)); 6613 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6614 PetscCall(ISRestoreIndices(newis, &newRows)); 6615 PetscCall(ISDestroy(&newis)); 6616 PetscCall(ISDestroy(&is)); 6617 } 6618 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6619 PetscFunctionReturn(PETSC_SUCCESS); 6620 } 6621 6622 /*@ 6623 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6624 of a set of rows of a matrix; using local numbering of rows. 6625 6626 Collective 6627 6628 Input Parameters: 6629 + mat - the matrix 6630 . is - index set of rows to remove 6631 . diag - value put in all diagonals of eliminated rows 6632 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6633 - b - optional vector of right-hand side, that will be adjusted by provided solution 6634 6635 Level: intermediate 6636 6637 Notes: 6638 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6639 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6640 6641 See `MatZeroRows()` for details on how this routine operates. 6642 6643 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6644 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6645 @*/ 6646 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6647 { 6648 PetscInt numRows; 6649 const PetscInt *rows; 6650 6651 PetscFunctionBegin; 6652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6653 PetscValidType(mat, 1); 6654 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6655 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6656 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6657 MatCheckPreallocated(mat, 1); 6658 6659 PetscCall(ISGetLocalSize(is, &numRows)); 6660 PetscCall(ISGetIndices(is, &rows)); 6661 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6662 PetscCall(ISRestoreIndices(is, &rows)); 6663 PetscFunctionReturn(PETSC_SUCCESS); 6664 } 6665 6666 /*@ 6667 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6668 of a set of rows and columns of a matrix; using local numbering of rows. 6669 6670 Collective 6671 6672 Input Parameters: 6673 + mat - the matrix 6674 . numRows - the number of rows to remove 6675 . rows - the global row indices 6676 . diag - value put in all diagonals of eliminated rows 6677 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6678 - b - optional vector of right-hand side, that will be adjusted by provided solution 6679 6680 Level: intermediate 6681 6682 Notes: 6683 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6684 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6685 6686 See `MatZeroRowsColumns()` for details on how this routine operates. 6687 6688 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6689 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6690 @*/ 6691 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6692 { 6693 IS is, newis; 6694 const PetscInt *newRows; 6695 6696 PetscFunctionBegin; 6697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6698 PetscValidType(mat, 1); 6699 if (numRows) PetscAssertPointer(rows, 3); 6700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6702 MatCheckPreallocated(mat, 1); 6703 6704 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6705 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6706 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6707 PetscCall(ISGetIndices(newis, &newRows)); 6708 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6709 PetscCall(ISRestoreIndices(newis, &newRows)); 6710 PetscCall(ISDestroy(&newis)); 6711 PetscCall(ISDestroy(&is)); 6712 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6713 PetscFunctionReturn(PETSC_SUCCESS); 6714 } 6715 6716 /*@ 6717 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6718 of a set of rows and columns of a matrix; using local numbering of rows. 6719 6720 Collective 6721 6722 Input Parameters: 6723 + mat - the matrix 6724 . is - index set of rows to remove 6725 . diag - value put in all diagonals of eliminated rows 6726 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6727 - b - optional vector of right-hand side, that will be adjusted by provided solution 6728 6729 Level: intermediate 6730 6731 Notes: 6732 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6733 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6734 6735 See `MatZeroRowsColumns()` for details on how this routine operates. 6736 6737 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6738 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6739 @*/ 6740 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6741 { 6742 PetscInt numRows; 6743 const PetscInt *rows; 6744 6745 PetscFunctionBegin; 6746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6747 PetscValidType(mat, 1); 6748 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6749 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6750 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6751 MatCheckPreallocated(mat, 1); 6752 6753 PetscCall(ISGetLocalSize(is, &numRows)); 6754 PetscCall(ISGetIndices(is, &rows)); 6755 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6756 PetscCall(ISRestoreIndices(is, &rows)); 6757 PetscFunctionReturn(PETSC_SUCCESS); 6758 } 6759 6760 /*@C 6761 MatGetSize - Returns the numbers of rows and columns in a matrix. 6762 6763 Not Collective 6764 6765 Input Parameter: 6766 . mat - the matrix 6767 6768 Output Parameters: 6769 + m - the number of global rows 6770 - n - the number of global columns 6771 6772 Level: beginner 6773 6774 Note: 6775 Both output parameters can be `NULL` on input. 6776 6777 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6778 @*/ 6779 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6780 { 6781 PetscFunctionBegin; 6782 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6783 if (m) *m = mat->rmap->N; 6784 if (n) *n = mat->cmap->N; 6785 PetscFunctionReturn(PETSC_SUCCESS); 6786 } 6787 6788 /*@C 6789 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6790 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6791 6792 Not Collective 6793 6794 Input Parameter: 6795 . mat - the matrix 6796 6797 Output Parameters: 6798 + m - the number of local rows, use `NULL` to not obtain this value 6799 - n - the number of local columns, use `NULL` to not obtain this value 6800 6801 Level: beginner 6802 6803 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6804 @*/ 6805 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6806 { 6807 PetscFunctionBegin; 6808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6809 if (m) PetscAssertPointer(m, 2); 6810 if (n) PetscAssertPointer(n, 3); 6811 if (m) *m = mat->rmap->n; 6812 if (n) *n = mat->cmap->n; 6813 PetscFunctionReturn(PETSC_SUCCESS); 6814 } 6815 6816 /*@ 6817 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6818 vector one multiplies this matrix by that are owned by this processor. 6819 6820 Not Collective, unless matrix has not been allocated, then collective 6821 6822 Input Parameter: 6823 . mat - the matrix 6824 6825 Output Parameters: 6826 + m - the global index of the first local column, use `NULL` to not obtain this value 6827 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6828 6829 Level: developer 6830 6831 Notes: 6832 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6833 6834 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6835 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6836 6837 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6838 the local values in the matrix. 6839 6840 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6841 Layouts](sec_matlayout) for details on matrix layouts. 6842 6843 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6844 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6845 @*/ 6846 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6847 { 6848 PetscFunctionBegin; 6849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6850 PetscValidType(mat, 1); 6851 if (m) PetscAssertPointer(m, 2); 6852 if (n) PetscAssertPointer(n, 3); 6853 MatCheckPreallocated(mat, 1); 6854 if (m) *m = mat->cmap->rstart; 6855 if (n) *n = mat->cmap->rend; 6856 PetscFunctionReturn(PETSC_SUCCESS); 6857 } 6858 6859 /*@C 6860 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6861 this MPI process. 6862 6863 Not Collective 6864 6865 Input Parameter: 6866 . mat - the matrix 6867 6868 Output Parameters: 6869 + m - the global index of the first local row, use `NULL` to not obtain this value 6870 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6871 6872 Level: beginner 6873 6874 Notes: 6875 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6876 6877 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6878 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6879 6880 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6881 the local values in the matrix. 6882 6883 The high argument is one more than the last element stored locally. 6884 6885 For all matrices it returns the range of matrix rows associated with rows of a vector that 6886 would contain the result of a matrix vector product with this matrix. See [Matrix 6887 Layouts](sec_matlayout) for details on matrix layouts. 6888 6889 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6890 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6891 @*/ 6892 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6893 { 6894 PetscFunctionBegin; 6895 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6896 PetscValidType(mat, 1); 6897 if (m) PetscAssertPointer(m, 2); 6898 if (n) PetscAssertPointer(n, 3); 6899 MatCheckPreallocated(mat, 1); 6900 if (m) *m = mat->rmap->rstart; 6901 if (n) *n = mat->rmap->rend; 6902 PetscFunctionReturn(PETSC_SUCCESS); 6903 } 6904 6905 /*@C 6906 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6907 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6908 6909 Not Collective, unless matrix has not been allocated 6910 6911 Input Parameter: 6912 . mat - the matrix 6913 6914 Output Parameter: 6915 . ranges - start of each processors portion plus one more than the total length at the end 6916 6917 Level: beginner 6918 6919 Notes: 6920 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6921 6922 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6923 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6924 6925 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6926 the local values in the matrix. 6927 6928 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6929 would contain the result of a matrix vector product with this matrix. See [Matrix 6930 Layouts](sec_matlayout) for details on matrix layouts. 6931 6932 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6933 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6934 `DMDAGetGhostCorners()`, `DM` 6935 @*/ 6936 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6937 { 6938 PetscFunctionBegin; 6939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6940 PetscValidType(mat, 1); 6941 MatCheckPreallocated(mat, 1); 6942 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6943 PetscFunctionReturn(PETSC_SUCCESS); 6944 } 6945 6946 /*@C 6947 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6948 vector one multiplies this vector by that are owned by each processor. 6949 6950 Not Collective, unless matrix has not been allocated 6951 6952 Input Parameter: 6953 . mat - the matrix 6954 6955 Output Parameter: 6956 . ranges - start of each processors portion plus one more than the total length at the end 6957 6958 Level: beginner 6959 6960 Notes: 6961 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6962 6963 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6964 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6965 6966 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6967 the local values in the matrix. 6968 6969 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6970 Layouts](sec_matlayout) for details on matrix layouts. 6971 6972 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6973 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6974 `DMDAGetGhostCorners()`, `DM` 6975 @*/ 6976 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6977 { 6978 PetscFunctionBegin; 6979 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6980 PetscValidType(mat, 1); 6981 MatCheckPreallocated(mat, 1); 6982 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6983 PetscFunctionReturn(PETSC_SUCCESS); 6984 } 6985 6986 /*@C 6987 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6988 6989 Not Collective 6990 6991 Input Parameter: 6992 . A - matrix 6993 6994 Output Parameters: 6995 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6996 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6997 6998 Level: intermediate 6999 7000 Note: 7001 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7002 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7003 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7004 details on matrix layouts. 7005 7006 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7007 @*/ 7008 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7009 { 7010 PetscErrorCode (*f)(Mat, IS *, IS *); 7011 7012 PetscFunctionBegin; 7013 MatCheckPreallocated(A, 1); 7014 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7015 if (f) { 7016 PetscCall((*f)(A, rows, cols)); 7017 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7018 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7019 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7020 } 7021 PetscFunctionReturn(PETSC_SUCCESS); 7022 } 7023 7024 /*@C 7025 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7026 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7027 to complete the factorization. 7028 7029 Collective 7030 7031 Input Parameters: 7032 + fact - the factorized matrix obtained with `MatGetFactor()` 7033 . mat - the matrix 7034 . row - row permutation 7035 . col - column permutation 7036 - info - structure containing 7037 .vb 7038 levels - number of levels of fill. 7039 expected fill - as ratio of original fill. 7040 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7041 missing diagonal entries) 7042 .ve 7043 7044 Level: developer 7045 7046 Notes: 7047 See [Matrix Factorization](sec_matfactor) for additional information. 7048 7049 Most users should employ the `KSP` interface for linear solvers 7050 instead of working directly with matrix algebra routines such as this. 7051 See, e.g., `KSPCreate()`. 7052 7053 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7054 7055 Developer Note: 7056 The Fortran interface is not autogenerated as the 7057 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7058 7059 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7060 `MatGetOrdering()`, `MatFactorInfo` 7061 @*/ 7062 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7063 { 7064 PetscFunctionBegin; 7065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7066 PetscValidType(mat, 2); 7067 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7068 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7069 PetscAssertPointer(info, 5); 7070 PetscAssertPointer(fact, 1); 7071 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7072 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7073 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7074 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7075 MatCheckPreallocated(mat, 2); 7076 7077 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7078 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7079 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7080 PetscFunctionReturn(PETSC_SUCCESS); 7081 } 7082 7083 /*@C 7084 MatICCFactorSymbolic - Performs symbolic incomplete 7085 Cholesky factorization for a symmetric matrix. Use 7086 `MatCholeskyFactorNumeric()` to complete the factorization. 7087 7088 Collective 7089 7090 Input Parameters: 7091 + fact - the factorized matrix obtained with `MatGetFactor()` 7092 . mat - the matrix to be factored 7093 . perm - row and column permutation 7094 - info - structure containing 7095 .vb 7096 levels - number of levels of fill. 7097 expected fill - as ratio of original fill. 7098 .ve 7099 7100 Level: developer 7101 7102 Notes: 7103 Most users should employ the `KSP` interface for linear solvers 7104 instead of working directly with matrix algebra routines such as this. 7105 See, e.g., `KSPCreate()`. 7106 7107 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7108 7109 Developer Note: 7110 The Fortran interface is not autogenerated as the 7111 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7112 7113 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7114 @*/ 7115 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7116 { 7117 PetscFunctionBegin; 7118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7119 PetscValidType(mat, 2); 7120 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7121 PetscAssertPointer(info, 4); 7122 PetscAssertPointer(fact, 1); 7123 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7124 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7125 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7127 MatCheckPreallocated(mat, 2); 7128 7129 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7130 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7131 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7132 PetscFunctionReturn(PETSC_SUCCESS); 7133 } 7134 7135 /*@C 7136 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7137 points to an array of valid matrices, they may be reused to store the new 7138 submatrices. 7139 7140 Collective 7141 7142 Input Parameters: 7143 + mat - the matrix 7144 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7145 . irow - index set of rows to extract 7146 . icol - index set of columns to extract 7147 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7148 7149 Output Parameter: 7150 . submat - the array of submatrices 7151 7152 Level: advanced 7153 7154 Notes: 7155 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7156 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7157 to extract a parallel submatrix. 7158 7159 Some matrix types place restrictions on the row and column 7160 indices, such as that they be sorted or that they be equal to each other. 7161 7162 The index sets may not have duplicate entries. 7163 7164 When extracting submatrices from a parallel matrix, each processor can 7165 form a different submatrix by setting the rows and columns of its 7166 individual index sets according to the local submatrix desired. 7167 7168 When finished using the submatrices, the user should destroy 7169 them with `MatDestroySubMatrices()`. 7170 7171 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7172 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7173 7174 This routine creates the matrices in submat; you should NOT create them before 7175 calling it. It also allocates the array of matrix pointers submat. 7176 7177 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7178 request one row/column in a block, they must request all rows/columns that are in 7179 that block. For example, if the block size is 2 you cannot request just row 0 and 7180 column 0. 7181 7182 Fortran Note: 7183 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7184 7185 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7186 @*/ 7187 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7188 { 7189 PetscInt i; 7190 PetscBool eq; 7191 7192 PetscFunctionBegin; 7193 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7194 PetscValidType(mat, 1); 7195 if (n) { 7196 PetscAssertPointer(irow, 3); 7197 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7198 PetscAssertPointer(icol, 4); 7199 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7200 } 7201 PetscAssertPointer(submat, 6); 7202 if (n && scall == MAT_REUSE_MATRIX) { 7203 PetscAssertPointer(*submat, 6); 7204 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7205 } 7206 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7207 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7208 MatCheckPreallocated(mat, 1); 7209 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7210 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7211 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7212 for (i = 0; i < n; i++) { 7213 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7214 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7215 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7216 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7217 if (mat->boundtocpu && mat->bindingpropagates) { 7218 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7219 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7220 } 7221 #endif 7222 } 7223 PetscFunctionReturn(PETSC_SUCCESS); 7224 } 7225 7226 /*@C 7227 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7228 7229 Collective 7230 7231 Input Parameters: 7232 + mat - the matrix 7233 . n - the number of submatrixes to be extracted 7234 . irow - index set of rows to extract 7235 . icol - index set of columns to extract 7236 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7237 7238 Output Parameter: 7239 . submat - the array of submatrices 7240 7241 Level: advanced 7242 7243 Note: 7244 This is used by `PCGASM` 7245 7246 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7247 @*/ 7248 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7249 { 7250 PetscInt i; 7251 PetscBool eq; 7252 7253 PetscFunctionBegin; 7254 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7255 PetscValidType(mat, 1); 7256 if (n) { 7257 PetscAssertPointer(irow, 3); 7258 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7259 PetscAssertPointer(icol, 4); 7260 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7261 } 7262 PetscAssertPointer(submat, 6); 7263 if (n && scall == MAT_REUSE_MATRIX) { 7264 PetscAssertPointer(*submat, 6); 7265 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7266 } 7267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7268 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7269 MatCheckPreallocated(mat, 1); 7270 7271 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7272 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7273 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7274 for (i = 0; i < n; i++) { 7275 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7276 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7277 } 7278 PetscFunctionReturn(PETSC_SUCCESS); 7279 } 7280 7281 /*@C 7282 MatDestroyMatrices - Destroys an array of matrices. 7283 7284 Collective 7285 7286 Input Parameters: 7287 + n - the number of local matrices 7288 - mat - the matrices (this is a pointer to the array of matrices) 7289 7290 Level: advanced 7291 7292 Note: 7293 Frees not only the matrices, but also the array that contains the matrices 7294 7295 Fortran Note: 7296 Does not free the `mat` array. 7297 7298 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7299 @*/ 7300 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7301 { 7302 PetscInt i; 7303 7304 PetscFunctionBegin; 7305 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7306 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7307 PetscAssertPointer(mat, 2); 7308 7309 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7310 7311 /* memory is allocated even if n = 0 */ 7312 PetscCall(PetscFree(*mat)); 7313 PetscFunctionReturn(PETSC_SUCCESS); 7314 } 7315 7316 /*@C 7317 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7318 7319 Collective 7320 7321 Input Parameters: 7322 + n - the number of local matrices 7323 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7324 sequence of `MatCreateSubMatrices()`) 7325 7326 Level: advanced 7327 7328 Note: 7329 Frees not only the matrices, but also the array that contains the matrices 7330 7331 Fortran Note: 7332 Does not free the `mat` array. 7333 7334 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7335 @*/ 7336 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7337 { 7338 Mat mat0; 7339 7340 PetscFunctionBegin; 7341 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7342 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7343 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7344 PetscAssertPointer(mat, 2); 7345 7346 mat0 = (*mat)[0]; 7347 if (mat0 && mat0->ops->destroysubmatrices) { 7348 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7349 } else { 7350 PetscCall(MatDestroyMatrices(n, mat)); 7351 } 7352 PetscFunctionReturn(PETSC_SUCCESS); 7353 } 7354 7355 /*@ 7356 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7357 7358 Collective 7359 7360 Input Parameter: 7361 . mat - the matrix 7362 7363 Output Parameter: 7364 . matstruct - the sequential matrix with the nonzero structure of `mat` 7365 7366 Level: developer 7367 7368 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7369 @*/ 7370 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7371 { 7372 PetscFunctionBegin; 7373 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7374 PetscAssertPointer(matstruct, 2); 7375 7376 PetscValidType(mat, 1); 7377 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7378 MatCheckPreallocated(mat, 1); 7379 7380 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7381 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7382 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7383 PetscFunctionReturn(PETSC_SUCCESS); 7384 } 7385 7386 /*@C 7387 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7388 7389 Collective 7390 7391 Input Parameter: 7392 . mat - the matrix 7393 7394 Level: advanced 7395 7396 Note: 7397 This is not needed, one can just call `MatDestroy()` 7398 7399 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7400 @*/ 7401 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7402 { 7403 PetscFunctionBegin; 7404 PetscAssertPointer(mat, 1); 7405 PetscCall(MatDestroy(mat)); 7406 PetscFunctionReturn(PETSC_SUCCESS); 7407 } 7408 7409 /*@ 7410 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7411 replaces the index sets by larger ones that represent submatrices with 7412 additional overlap. 7413 7414 Collective 7415 7416 Input Parameters: 7417 + mat - the matrix 7418 . n - the number of index sets 7419 . is - the array of index sets (these index sets will changed during the call) 7420 - ov - the additional overlap requested 7421 7422 Options Database Key: 7423 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7424 7425 Level: developer 7426 7427 Note: 7428 The computed overlap preserves the matrix block sizes when the blocks are square. 7429 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7430 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7431 7432 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7433 @*/ 7434 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7435 { 7436 PetscInt i, bs, cbs; 7437 7438 PetscFunctionBegin; 7439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7440 PetscValidType(mat, 1); 7441 PetscValidLogicalCollectiveInt(mat, n, 2); 7442 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7443 if (n) { 7444 PetscAssertPointer(is, 3); 7445 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7446 } 7447 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7448 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7449 MatCheckPreallocated(mat, 1); 7450 7451 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7452 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7453 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7454 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7455 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7456 if (bs == cbs) { 7457 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7458 } 7459 PetscFunctionReturn(PETSC_SUCCESS); 7460 } 7461 7462 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7463 7464 /*@ 7465 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7466 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7467 additional overlap. 7468 7469 Collective 7470 7471 Input Parameters: 7472 + mat - the matrix 7473 . n - the number of index sets 7474 . is - the array of index sets (these index sets will changed during the call) 7475 - ov - the additional overlap requested 7476 7477 ` Options Database Key: 7478 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7479 7480 Level: developer 7481 7482 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7483 @*/ 7484 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7485 { 7486 PetscInt i; 7487 7488 PetscFunctionBegin; 7489 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7490 PetscValidType(mat, 1); 7491 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7492 if (n) { 7493 PetscAssertPointer(is, 3); 7494 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7495 } 7496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7498 MatCheckPreallocated(mat, 1); 7499 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7500 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7501 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7502 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7503 PetscFunctionReturn(PETSC_SUCCESS); 7504 } 7505 7506 /*@ 7507 MatGetBlockSize - Returns the matrix block size. 7508 7509 Not Collective 7510 7511 Input Parameter: 7512 . mat - the matrix 7513 7514 Output Parameter: 7515 . bs - block size 7516 7517 Level: intermediate 7518 7519 Notes: 7520 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7521 7522 If the block size has not been set yet this routine returns 1. 7523 7524 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7525 @*/ 7526 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7527 { 7528 PetscFunctionBegin; 7529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7530 PetscAssertPointer(bs, 2); 7531 *bs = PetscAbs(mat->rmap->bs); 7532 PetscFunctionReturn(PETSC_SUCCESS); 7533 } 7534 7535 /*@ 7536 MatGetBlockSizes - Returns the matrix block row and column sizes. 7537 7538 Not Collective 7539 7540 Input Parameter: 7541 . mat - the matrix 7542 7543 Output Parameters: 7544 + rbs - row block size 7545 - cbs - column block size 7546 7547 Level: intermediate 7548 7549 Notes: 7550 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7551 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7552 7553 If a block size has not been set yet this routine returns 1. 7554 7555 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7556 @*/ 7557 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7558 { 7559 PetscFunctionBegin; 7560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7561 if (rbs) PetscAssertPointer(rbs, 2); 7562 if (cbs) PetscAssertPointer(cbs, 3); 7563 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7564 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7565 PetscFunctionReturn(PETSC_SUCCESS); 7566 } 7567 7568 /*@ 7569 MatSetBlockSize - Sets the matrix block size. 7570 7571 Logically Collective 7572 7573 Input Parameters: 7574 + mat - the matrix 7575 - bs - block size 7576 7577 Level: intermediate 7578 7579 Notes: 7580 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7581 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7582 7583 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7584 is compatible with the matrix local sizes. 7585 7586 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7587 @*/ 7588 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7589 { 7590 PetscFunctionBegin; 7591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7592 PetscValidLogicalCollectiveInt(mat, bs, 2); 7593 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7594 PetscFunctionReturn(PETSC_SUCCESS); 7595 } 7596 7597 typedef struct { 7598 PetscInt n; 7599 IS *is; 7600 Mat *mat; 7601 PetscObjectState nonzerostate; 7602 Mat C; 7603 } EnvelopeData; 7604 7605 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7606 { 7607 EnvelopeData *edata = (EnvelopeData *)ptr; 7608 7609 PetscFunctionBegin; 7610 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7611 PetscCall(PetscFree(edata->is)); 7612 PetscCall(PetscFree(edata)); 7613 PetscFunctionReturn(PETSC_SUCCESS); 7614 } 7615 7616 /*@ 7617 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7618 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7619 7620 Collective 7621 7622 Input Parameter: 7623 . mat - the matrix 7624 7625 Level: intermediate 7626 7627 Notes: 7628 There can be zeros within the blocks 7629 7630 The blocks can overlap between processes, including laying on more than two processes 7631 7632 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7633 @*/ 7634 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7635 { 7636 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7637 PetscInt *diag, *odiag, sc; 7638 VecScatter scatter; 7639 PetscScalar *seqv; 7640 const PetscScalar *parv; 7641 const PetscInt *ia, *ja; 7642 PetscBool set, flag, done; 7643 Mat AA = mat, A; 7644 MPI_Comm comm; 7645 PetscMPIInt rank, size, tag; 7646 MPI_Status status; 7647 PetscContainer container; 7648 EnvelopeData *edata; 7649 Vec seq, par; 7650 IS isglobal; 7651 7652 PetscFunctionBegin; 7653 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7654 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7655 if (!set || !flag) { 7656 /* TODO: only needs nonzero structure of transpose */ 7657 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7658 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7659 } 7660 PetscCall(MatAIJGetLocalMat(AA, &A)); 7661 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7662 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7663 7664 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7665 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7666 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7667 PetscCallMPI(MPI_Comm_size(comm, &size)); 7668 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7669 7670 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7671 7672 if (rank > 0) { 7673 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7674 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7675 } 7676 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7677 for (i = 0; i < n; i++) { 7678 env = PetscMax(env, ja[ia[i + 1] - 1]); 7679 II = rstart + i; 7680 if (env == II) { 7681 starts[lblocks] = tbs; 7682 sizes[lblocks++] = 1 + II - tbs; 7683 tbs = 1 + II; 7684 } 7685 } 7686 if (rank < size - 1) { 7687 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7688 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7689 } 7690 7691 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7692 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7693 PetscCall(MatDestroy(&A)); 7694 7695 PetscCall(PetscNew(&edata)); 7696 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7697 edata->n = lblocks; 7698 /* create IS needed for extracting blocks from the original matrix */ 7699 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7700 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7701 7702 /* Create the resulting inverse matrix structure with preallocation information */ 7703 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7704 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7705 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7706 PetscCall(MatSetType(edata->C, MATAIJ)); 7707 7708 /* Communicate the start and end of each row, from each block to the correct rank */ 7709 /* TODO: Use PetscSF instead of VecScatter */ 7710 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7711 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7712 PetscCall(VecGetArrayWrite(seq, &seqv)); 7713 for (PetscInt i = 0; i < lblocks; i++) { 7714 for (PetscInt j = 0; j < sizes[i]; j++) { 7715 seqv[cnt] = starts[i]; 7716 seqv[cnt + 1] = starts[i] + sizes[i]; 7717 cnt += 2; 7718 } 7719 } 7720 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7721 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7722 sc -= cnt; 7723 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7724 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7725 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7726 PetscCall(ISDestroy(&isglobal)); 7727 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7728 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7729 PetscCall(VecScatterDestroy(&scatter)); 7730 PetscCall(VecDestroy(&seq)); 7731 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7732 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7733 PetscCall(VecGetArrayRead(par, &parv)); 7734 cnt = 0; 7735 PetscCall(MatGetSize(mat, NULL, &n)); 7736 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7737 PetscInt start, end, d = 0, od = 0; 7738 7739 start = (PetscInt)PetscRealPart(parv[cnt]); 7740 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7741 cnt += 2; 7742 7743 if (start < cstart) { 7744 od += cstart - start + n - cend; 7745 d += cend - cstart; 7746 } else if (start < cend) { 7747 od += n - cend; 7748 d += cend - start; 7749 } else od += n - start; 7750 if (end <= cstart) { 7751 od -= cstart - end + n - cend; 7752 d -= cend - cstart; 7753 } else if (end < cend) { 7754 od -= n - cend; 7755 d -= cend - end; 7756 } else od -= n - end; 7757 7758 odiag[i] = od; 7759 diag[i] = d; 7760 } 7761 PetscCall(VecRestoreArrayRead(par, &parv)); 7762 PetscCall(VecDestroy(&par)); 7763 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7764 PetscCall(PetscFree2(diag, odiag)); 7765 PetscCall(PetscFree2(sizes, starts)); 7766 7767 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7768 PetscCall(PetscContainerSetPointer(container, edata)); 7769 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7770 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7771 PetscCall(PetscObjectDereference((PetscObject)container)); 7772 PetscFunctionReturn(PETSC_SUCCESS); 7773 } 7774 7775 /*@ 7776 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7777 7778 Collective 7779 7780 Input Parameters: 7781 + A - the matrix 7782 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7783 7784 Output Parameter: 7785 . C - matrix with inverted block diagonal of `A` 7786 7787 Level: advanced 7788 7789 Note: 7790 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7791 7792 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7793 @*/ 7794 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7795 { 7796 PetscContainer container; 7797 EnvelopeData *edata; 7798 PetscObjectState nonzerostate; 7799 7800 PetscFunctionBegin; 7801 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7802 if (!container) { 7803 PetscCall(MatComputeVariableBlockEnvelope(A)); 7804 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7805 } 7806 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7807 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7808 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7809 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7810 7811 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7812 *C = edata->C; 7813 7814 for (PetscInt i = 0; i < edata->n; i++) { 7815 Mat D; 7816 PetscScalar *dvalues; 7817 7818 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7819 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7820 PetscCall(MatSeqDenseInvert(D)); 7821 PetscCall(MatDenseGetArray(D, &dvalues)); 7822 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7823 PetscCall(MatDestroy(&D)); 7824 } 7825 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7826 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7827 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7828 PetscFunctionReturn(PETSC_SUCCESS); 7829 } 7830 7831 /*@ 7832 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7833 7834 Not Collective 7835 7836 Input Parameters: 7837 + mat - the matrix 7838 . nblocks - the number of blocks on this process, each block can only exist on a single process 7839 - bsizes - the block sizes 7840 7841 Level: intermediate 7842 7843 Notes: 7844 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7845 7846 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. 7847 7848 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7849 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7850 @*/ 7851 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7852 { 7853 PetscInt ncnt = 0, nlocal; 7854 7855 PetscFunctionBegin; 7856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7857 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7858 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); 7859 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7860 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); 7861 PetscCall(PetscFree(mat->bsizes)); 7862 mat->nblocks = nblocks; 7863 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7864 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7865 PetscFunctionReturn(PETSC_SUCCESS); 7866 } 7867 7868 /*@C 7869 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7870 7871 Not Collective; No Fortran Support 7872 7873 Input Parameter: 7874 . mat - the matrix 7875 7876 Output Parameters: 7877 + nblocks - the number of blocks on this process 7878 - bsizes - the block sizes 7879 7880 Level: intermediate 7881 7882 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7883 @*/ 7884 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7885 { 7886 PetscFunctionBegin; 7887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7888 if (nblocks) *nblocks = mat->nblocks; 7889 if (bsizes) *bsizes = mat->bsizes; 7890 PetscFunctionReturn(PETSC_SUCCESS); 7891 } 7892 7893 /*@ 7894 MatSetBlockSizes - Sets the matrix block row and column sizes. 7895 7896 Logically Collective 7897 7898 Input Parameters: 7899 + mat - the matrix 7900 . rbs - row block size 7901 - cbs - column block size 7902 7903 Level: intermediate 7904 7905 Notes: 7906 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7907 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7908 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7909 7910 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7911 are compatible with the matrix local sizes. 7912 7913 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7914 7915 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7916 @*/ 7917 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7918 { 7919 PetscFunctionBegin; 7920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7921 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7922 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7923 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7924 if (mat->rmap->refcnt) { 7925 ISLocalToGlobalMapping l2g = NULL; 7926 PetscLayout nmap = NULL; 7927 7928 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7929 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7930 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7931 mat->rmap = nmap; 7932 mat->rmap->mapping = l2g; 7933 } 7934 if (mat->cmap->refcnt) { 7935 ISLocalToGlobalMapping l2g = NULL; 7936 PetscLayout nmap = NULL; 7937 7938 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7939 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7940 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7941 mat->cmap = nmap; 7942 mat->cmap->mapping = l2g; 7943 } 7944 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7945 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7946 PetscFunctionReturn(PETSC_SUCCESS); 7947 } 7948 7949 /*@ 7950 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7951 7952 Logically Collective 7953 7954 Input Parameters: 7955 + mat - the matrix 7956 . fromRow - matrix from which to copy row block size 7957 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7958 7959 Level: developer 7960 7961 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7962 @*/ 7963 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7964 { 7965 PetscFunctionBegin; 7966 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7967 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7968 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7969 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7970 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7971 PetscFunctionReturn(PETSC_SUCCESS); 7972 } 7973 7974 /*@ 7975 MatResidual - Default routine to calculate the residual r = b - Ax 7976 7977 Collective 7978 7979 Input Parameters: 7980 + mat - the matrix 7981 . b - the right-hand-side 7982 - x - the approximate solution 7983 7984 Output Parameter: 7985 . r - location to store the residual 7986 7987 Level: developer 7988 7989 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7990 @*/ 7991 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7992 { 7993 PetscFunctionBegin; 7994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7995 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7996 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7997 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7998 PetscValidType(mat, 1); 7999 MatCheckPreallocated(mat, 1); 8000 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8001 if (!mat->ops->residual) { 8002 PetscCall(MatMult(mat, x, r)); 8003 PetscCall(VecAYPX(r, -1.0, b)); 8004 } else { 8005 PetscUseTypeMethod(mat, residual, b, x, r); 8006 } 8007 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8008 PetscFunctionReturn(PETSC_SUCCESS); 8009 } 8010 8011 /*MC 8012 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8013 8014 Synopsis: 8015 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8016 8017 Not Collective 8018 8019 Input Parameters: 8020 + A - the matrix 8021 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8022 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8023 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8024 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8025 always used. 8026 8027 Output Parameters: 8028 + n - number of local rows in the (possibly compressed) matrix 8029 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8030 . ja - the column indices 8031 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8032 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8033 8034 Level: developer 8035 8036 Note: 8037 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8038 8039 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8040 M*/ 8041 8042 /*MC 8043 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8044 8045 Synopsis: 8046 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8047 8048 Not Collective 8049 8050 Input Parameters: 8051 + A - the matrix 8052 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8053 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8054 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8055 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8056 always used. 8057 . n - number of local rows in the (possibly compressed) matrix 8058 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8059 . ja - the column indices 8060 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8061 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8062 8063 Level: developer 8064 8065 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8066 M*/ 8067 8068 /*@C 8069 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8070 8071 Collective 8072 8073 Input Parameters: 8074 + mat - the matrix 8075 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8076 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8077 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8078 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8079 always used. 8080 8081 Output Parameters: 8082 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8083 . 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 8084 . ja - the column indices, use `NULL` if not needed 8085 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8086 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8087 8088 Level: developer 8089 8090 Notes: 8091 You CANNOT change any of the ia[] or ja[] values. 8092 8093 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8094 8095 Fortran Notes: 8096 Use 8097 .vb 8098 PetscInt, pointer :: ia(:),ja(:) 8099 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8100 ! Access the ith and jth entries via ia(i) and ja(j) 8101 .ve 8102 8103 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8104 8105 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8106 @*/ 8107 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8108 { 8109 PetscFunctionBegin; 8110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8111 PetscValidType(mat, 1); 8112 if (n) PetscAssertPointer(n, 5); 8113 if (ia) PetscAssertPointer(ia, 6); 8114 if (ja) PetscAssertPointer(ja, 7); 8115 if (done) PetscAssertPointer(done, 8); 8116 MatCheckPreallocated(mat, 1); 8117 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8118 else { 8119 if (done) *done = PETSC_TRUE; 8120 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8121 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8122 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8123 } 8124 PetscFunctionReturn(PETSC_SUCCESS); 8125 } 8126 8127 /*@C 8128 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8129 8130 Collective 8131 8132 Input Parameters: 8133 + mat - the matrix 8134 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8135 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8136 symmetrized 8137 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8138 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8139 always used. 8140 . n - number of columns in the (possibly compressed) matrix 8141 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8142 - ja - the row indices 8143 8144 Output Parameter: 8145 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8146 8147 Level: developer 8148 8149 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8150 @*/ 8151 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8152 { 8153 PetscFunctionBegin; 8154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8155 PetscValidType(mat, 1); 8156 PetscAssertPointer(n, 5); 8157 if (ia) PetscAssertPointer(ia, 6); 8158 if (ja) PetscAssertPointer(ja, 7); 8159 PetscAssertPointer(done, 8); 8160 MatCheckPreallocated(mat, 1); 8161 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8162 else { 8163 *done = PETSC_TRUE; 8164 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8165 } 8166 PetscFunctionReturn(PETSC_SUCCESS); 8167 } 8168 8169 /*@C 8170 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8171 8172 Collective 8173 8174 Input Parameters: 8175 + mat - the matrix 8176 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8177 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8178 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8179 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8180 always used. 8181 . n - size of (possibly compressed) matrix 8182 . ia - the row pointers 8183 - ja - the column indices 8184 8185 Output Parameter: 8186 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8187 8188 Level: developer 8189 8190 Note: 8191 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8192 us of the array after it has been restored. If you pass `NULL`, it will 8193 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8194 8195 Fortran Note: 8196 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8197 8198 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8199 @*/ 8200 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8201 { 8202 PetscFunctionBegin; 8203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8204 PetscValidType(mat, 1); 8205 if (ia) PetscAssertPointer(ia, 6); 8206 if (ja) PetscAssertPointer(ja, 7); 8207 if (done) PetscAssertPointer(done, 8); 8208 MatCheckPreallocated(mat, 1); 8209 8210 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8211 else { 8212 if (done) *done = PETSC_TRUE; 8213 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8214 if (n) *n = 0; 8215 if (ia) *ia = NULL; 8216 if (ja) *ja = NULL; 8217 } 8218 PetscFunctionReturn(PETSC_SUCCESS); 8219 } 8220 8221 /*@C 8222 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8223 8224 Collective 8225 8226 Input Parameters: 8227 + mat - the matrix 8228 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8229 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8230 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8231 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8232 always used. 8233 8234 Output Parameters: 8235 + n - size of (possibly compressed) matrix 8236 . ia - the column pointers 8237 . ja - the row indices 8238 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8239 8240 Level: developer 8241 8242 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8243 @*/ 8244 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8245 { 8246 PetscFunctionBegin; 8247 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8248 PetscValidType(mat, 1); 8249 if (ia) PetscAssertPointer(ia, 6); 8250 if (ja) PetscAssertPointer(ja, 7); 8251 PetscAssertPointer(done, 8); 8252 MatCheckPreallocated(mat, 1); 8253 8254 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8255 else { 8256 *done = PETSC_TRUE; 8257 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8258 if (n) *n = 0; 8259 if (ia) *ia = NULL; 8260 if (ja) *ja = NULL; 8261 } 8262 PetscFunctionReturn(PETSC_SUCCESS); 8263 } 8264 8265 /*@ 8266 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8267 `MatGetColumnIJ()`. 8268 8269 Collective 8270 8271 Input Parameters: 8272 + mat - the matrix 8273 . ncolors - maximum color value 8274 . n - number of entries in colorarray 8275 - colorarray - array indicating color for each column 8276 8277 Output Parameter: 8278 . iscoloring - coloring generated using colorarray information 8279 8280 Level: developer 8281 8282 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8283 @*/ 8284 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8285 { 8286 PetscFunctionBegin; 8287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8288 PetscValidType(mat, 1); 8289 PetscAssertPointer(colorarray, 4); 8290 PetscAssertPointer(iscoloring, 5); 8291 MatCheckPreallocated(mat, 1); 8292 8293 if (!mat->ops->coloringpatch) { 8294 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8295 } else { 8296 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8297 } 8298 PetscFunctionReturn(PETSC_SUCCESS); 8299 } 8300 8301 /*@ 8302 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8303 8304 Logically Collective 8305 8306 Input Parameter: 8307 . mat - the factored matrix to be reset 8308 8309 Level: developer 8310 8311 Notes: 8312 This routine should be used only with factored matrices formed by in-place 8313 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8314 format). This option can save memory, for example, when solving nonlinear 8315 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8316 ILU(0) preconditioner. 8317 8318 One can specify in-place ILU(0) factorization by calling 8319 .vb 8320 PCType(pc,PCILU); 8321 PCFactorSeUseInPlace(pc); 8322 .ve 8323 or by using the options -pc_type ilu -pc_factor_in_place 8324 8325 In-place factorization ILU(0) can also be used as a local 8326 solver for the blocks within the block Jacobi or additive Schwarz 8327 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8328 for details on setting local solver options. 8329 8330 Most users should employ the `KSP` interface for linear solvers 8331 instead of working directly with matrix algebra routines such as this. 8332 See, e.g., `KSPCreate()`. 8333 8334 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8335 @*/ 8336 PetscErrorCode MatSetUnfactored(Mat mat) 8337 { 8338 PetscFunctionBegin; 8339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8340 PetscValidType(mat, 1); 8341 MatCheckPreallocated(mat, 1); 8342 mat->factortype = MAT_FACTOR_NONE; 8343 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8344 PetscUseTypeMethod(mat, setunfactored); 8345 PetscFunctionReturn(PETSC_SUCCESS); 8346 } 8347 8348 /*MC 8349 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8350 8351 Synopsis: 8352 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8353 8354 Not Collective 8355 8356 Input Parameter: 8357 . x - matrix 8358 8359 Output Parameters: 8360 + xx_v - the Fortran pointer to the array 8361 - ierr - error code 8362 8363 Example of Usage: 8364 .vb 8365 PetscScalar, pointer xx_v(:,:) 8366 .... 8367 call MatDenseGetArrayF90(x,xx_v,ierr) 8368 a = xx_v(3) 8369 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8370 .ve 8371 8372 Level: advanced 8373 8374 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8375 M*/ 8376 8377 /*MC 8378 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8379 accessed with `MatDenseGetArrayF90()`. 8380 8381 Synopsis: 8382 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8383 8384 Not Collective 8385 8386 Input Parameters: 8387 + x - matrix 8388 - xx_v - the Fortran90 pointer to the array 8389 8390 Output Parameter: 8391 . ierr - error code 8392 8393 Example of Usage: 8394 .vb 8395 PetscScalar, pointer xx_v(:,:) 8396 .... 8397 call MatDenseGetArrayF90(x,xx_v,ierr) 8398 a = xx_v(3) 8399 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8400 .ve 8401 8402 Level: advanced 8403 8404 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8405 M*/ 8406 8407 /*MC 8408 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8409 8410 Synopsis: 8411 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8412 8413 Not Collective 8414 8415 Input Parameter: 8416 . x - matrix 8417 8418 Output Parameters: 8419 + xx_v - the Fortran pointer to the array 8420 - ierr - error code 8421 8422 Example of Usage: 8423 .vb 8424 PetscScalar, pointer xx_v(:) 8425 .... 8426 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8427 a = xx_v(3) 8428 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8429 .ve 8430 8431 Level: advanced 8432 8433 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8434 M*/ 8435 8436 /*MC 8437 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8438 accessed with `MatSeqAIJGetArrayF90()`. 8439 8440 Synopsis: 8441 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8442 8443 Not Collective 8444 8445 Input Parameters: 8446 + x - matrix 8447 - xx_v - the Fortran90 pointer to the array 8448 8449 Output Parameter: 8450 . ierr - error code 8451 8452 Example of Usage: 8453 .vb 8454 PetscScalar, pointer xx_v(:) 8455 .... 8456 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8457 a = xx_v(3) 8458 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8459 .ve 8460 8461 Level: advanced 8462 8463 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8464 M*/ 8465 8466 /*@ 8467 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8468 as the original matrix. 8469 8470 Collective 8471 8472 Input Parameters: 8473 + mat - the original matrix 8474 . isrow - parallel `IS` containing the rows this processor should obtain 8475 . 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. 8476 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8477 8478 Output Parameter: 8479 . newmat - the new submatrix, of the same type as the original matrix 8480 8481 Level: advanced 8482 8483 Notes: 8484 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8485 8486 Some matrix types place restrictions on the row and column indices, such 8487 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; 8488 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8489 8490 The index sets may not have duplicate entries. 8491 8492 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8493 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8494 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8495 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8496 you are finished using it. 8497 8498 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8499 the input matrix. 8500 8501 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8502 8503 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8504 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8505 8506 Example usage: 8507 Consider the following 8x8 matrix with 34 non-zero values, that is 8508 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8509 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8510 as follows 8511 .vb 8512 1 2 0 | 0 3 0 | 0 4 8513 Proc0 0 5 6 | 7 0 0 | 8 0 8514 9 0 10 | 11 0 0 | 12 0 8515 ------------------------------------- 8516 13 0 14 | 15 16 17 | 0 0 8517 Proc1 0 18 0 | 19 20 21 | 0 0 8518 0 0 0 | 22 23 0 | 24 0 8519 ------------------------------------- 8520 Proc2 25 26 27 | 0 0 28 | 29 0 8521 30 0 0 | 31 32 33 | 0 34 8522 .ve 8523 8524 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8525 8526 .vb 8527 2 0 | 0 3 0 | 0 8528 Proc0 5 6 | 7 0 0 | 8 8529 ------------------------------- 8530 Proc1 18 0 | 19 20 21 | 0 8531 ------------------------------- 8532 Proc2 26 27 | 0 0 28 | 29 8533 0 0 | 31 32 33 | 0 8534 .ve 8535 8536 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8537 @*/ 8538 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8539 { 8540 PetscMPIInt size; 8541 Mat *local; 8542 IS iscoltmp; 8543 PetscBool flg; 8544 8545 PetscFunctionBegin; 8546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8547 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8548 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8549 PetscAssertPointer(newmat, 5); 8550 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8551 PetscValidType(mat, 1); 8552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8553 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8554 8555 MatCheckPreallocated(mat, 1); 8556 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8557 8558 if (!iscol || isrow == iscol) { 8559 PetscBool stride; 8560 PetscMPIInt grabentirematrix = 0, grab; 8561 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8562 if (stride) { 8563 PetscInt first, step, n, rstart, rend; 8564 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8565 if (step == 1) { 8566 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8567 if (rstart == first) { 8568 PetscCall(ISGetLocalSize(isrow, &n)); 8569 if (n == rend - rstart) grabentirematrix = 1; 8570 } 8571 } 8572 } 8573 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8574 if (grab) { 8575 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8576 if (cll == MAT_INITIAL_MATRIX) { 8577 *newmat = mat; 8578 PetscCall(PetscObjectReference((PetscObject)mat)); 8579 } 8580 PetscFunctionReturn(PETSC_SUCCESS); 8581 } 8582 } 8583 8584 if (!iscol) { 8585 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8586 } else { 8587 iscoltmp = iscol; 8588 } 8589 8590 /* if original matrix is on just one processor then use submatrix generated */ 8591 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8592 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8593 goto setproperties; 8594 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8595 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8596 *newmat = *local; 8597 PetscCall(PetscFree(local)); 8598 goto setproperties; 8599 } else if (!mat->ops->createsubmatrix) { 8600 /* Create a new matrix type that implements the operation using the full matrix */ 8601 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8602 switch (cll) { 8603 case MAT_INITIAL_MATRIX: 8604 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8605 break; 8606 case MAT_REUSE_MATRIX: 8607 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8608 break; 8609 default: 8610 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8611 } 8612 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8613 goto setproperties; 8614 } 8615 8616 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8617 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8618 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8619 8620 setproperties: 8621 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8622 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8623 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8624 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8625 PetscFunctionReturn(PETSC_SUCCESS); 8626 } 8627 8628 /*@ 8629 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8630 8631 Not Collective 8632 8633 Input Parameters: 8634 + A - the matrix we wish to propagate options from 8635 - B - the matrix we wish to propagate options to 8636 8637 Level: beginner 8638 8639 Note: 8640 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8641 8642 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8643 @*/ 8644 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8645 { 8646 PetscFunctionBegin; 8647 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8648 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8649 B->symmetry_eternal = A->symmetry_eternal; 8650 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8651 B->symmetric = A->symmetric; 8652 B->structurally_symmetric = A->structurally_symmetric; 8653 B->spd = A->spd; 8654 B->hermitian = A->hermitian; 8655 PetscFunctionReturn(PETSC_SUCCESS); 8656 } 8657 8658 /*@ 8659 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8660 used during the assembly process to store values that belong to 8661 other processors. 8662 8663 Not Collective 8664 8665 Input Parameters: 8666 + mat - the matrix 8667 . size - the initial size of the stash. 8668 - bsize - the initial size of the block-stash(if used). 8669 8670 Options Database Keys: 8671 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8672 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8673 8674 Level: intermediate 8675 8676 Notes: 8677 The block-stash is used for values set with `MatSetValuesBlocked()` while 8678 the stash is used for values set with `MatSetValues()` 8679 8680 Run with the option -info and look for output of the form 8681 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8682 to determine the appropriate value, MM, to use for size and 8683 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8684 to determine the value, BMM to use for bsize 8685 8686 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8687 @*/ 8688 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8689 { 8690 PetscFunctionBegin; 8691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8692 PetscValidType(mat, 1); 8693 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8694 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8695 PetscFunctionReturn(PETSC_SUCCESS); 8696 } 8697 8698 /*@ 8699 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8700 the matrix 8701 8702 Neighbor-wise Collective 8703 8704 Input Parameters: 8705 + A - the matrix 8706 . x - the vector to be multiplied by the interpolation operator 8707 - y - the vector to be added to the result 8708 8709 Output Parameter: 8710 . w - the resulting vector 8711 8712 Level: intermediate 8713 8714 Notes: 8715 `w` may be the same vector as `y`. 8716 8717 This allows one to use either the restriction or interpolation (its transpose) 8718 matrix to do the interpolation 8719 8720 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8721 @*/ 8722 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8723 { 8724 PetscInt M, N, Ny; 8725 8726 PetscFunctionBegin; 8727 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8728 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8729 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8730 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8731 PetscCall(MatGetSize(A, &M, &N)); 8732 PetscCall(VecGetSize(y, &Ny)); 8733 if (M == Ny) { 8734 PetscCall(MatMultAdd(A, x, y, w)); 8735 } else { 8736 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8737 } 8738 PetscFunctionReturn(PETSC_SUCCESS); 8739 } 8740 8741 /*@ 8742 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8743 the matrix 8744 8745 Neighbor-wise Collective 8746 8747 Input Parameters: 8748 + A - the matrix 8749 - x - the vector to be interpolated 8750 8751 Output Parameter: 8752 . y - the resulting vector 8753 8754 Level: intermediate 8755 8756 Note: 8757 This allows one to use either the restriction or interpolation (its transpose) 8758 matrix to do the interpolation 8759 8760 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8761 @*/ 8762 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8763 { 8764 PetscInt M, N, Ny; 8765 8766 PetscFunctionBegin; 8767 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8768 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8769 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8770 PetscCall(MatGetSize(A, &M, &N)); 8771 PetscCall(VecGetSize(y, &Ny)); 8772 if (M == Ny) { 8773 PetscCall(MatMult(A, x, y)); 8774 } else { 8775 PetscCall(MatMultTranspose(A, x, y)); 8776 } 8777 PetscFunctionReturn(PETSC_SUCCESS); 8778 } 8779 8780 /*@ 8781 MatRestrict - $y = A*x$ or $A^T*x$ 8782 8783 Neighbor-wise Collective 8784 8785 Input Parameters: 8786 + A - the matrix 8787 - x - the vector to be restricted 8788 8789 Output Parameter: 8790 . y - the resulting vector 8791 8792 Level: intermediate 8793 8794 Note: 8795 This allows one to use either the restriction or interpolation (its transpose) 8796 matrix to do the restriction 8797 8798 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8799 @*/ 8800 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8801 { 8802 PetscInt M, N, Nx; 8803 8804 PetscFunctionBegin; 8805 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8806 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8807 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8808 PetscCall(MatGetSize(A, &M, &N)); 8809 PetscCall(VecGetSize(x, &Nx)); 8810 if (M == Nx) { 8811 PetscCall(MatMultTranspose(A, x, y)); 8812 } else { 8813 PetscCall(MatMult(A, x, y)); 8814 } 8815 PetscFunctionReturn(PETSC_SUCCESS); 8816 } 8817 8818 /*@ 8819 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8820 8821 Neighbor-wise Collective 8822 8823 Input Parameters: 8824 + A - the matrix 8825 . x - the input dense matrix to be multiplied 8826 - w - the input dense matrix to be added to the result 8827 8828 Output Parameter: 8829 . y - the output dense matrix 8830 8831 Level: intermediate 8832 8833 Note: 8834 This allows one to use either the restriction or interpolation (its transpose) 8835 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8836 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8837 8838 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8839 @*/ 8840 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8841 { 8842 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8843 PetscBool trans = PETSC_TRUE; 8844 MatReuse reuse = MAT_INITIAL_MATRIX; 8845 8846 PetscFunctionBegin; 8847 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8848 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8849 PetscValidType(x, 2); 8850 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8851 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8852 PetscCall(MatGetSize(A, &M, &N)); 8853 PetscCall(MatGetSize(x, &Mx, &Nx)); 8854 if (N == Mx) trans = PETSC_FALSE; 8855 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); 8856 Mo = trans ? N : M; 8857 if (*y) { 8858 PetscCall(MatGetSize(*y, &My, &Ny)); 8859 if (Mo == My && Nx == Ny) { 8860 reuse = MAT_REUSE_MATRIX; 8861 } else { 8862 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); 8863 PetscCall(MatDestroy(y)); 8864 } 8865 } 8866 8867 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8868 PetscBool flg; 8869 8870 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8871 if (w) { 8872 PetscInt My, Ny, Mw, Nw; 8873 8874 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8875 PetscCall(MatGetSize(*y, &My, &Ny)); 8876 PetscCall(MatGetSize(w, &Mw, &Nw)); 8877 if (!flg || My != Mw || Ny != Nw) w = NULL; 8878 } 8879 if (!w) { 8880 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8881 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8882 PetscCall(PetscObjectDereference((PetscObject)w)); 8883 } else { 8884 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8885 } 8886 } 8887 if (!trans) { 8888 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8889 } else { 8890 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8891 } 8892 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8893 PetscFunctionReturn(PETSC_SUCCESS); 8894 } 8895 8896 /*@ 8897 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8898 8899 Neighbor-wise Collective 8900 8901 Input Parameters: 8902 + A - the matrix 8903 - x - the input dense matrix 8904 8905 Output Parameter: 8906 . y - the output dense matrix 8907 8908 Level: intermediate 8909 8910 Note: 8911 This allows one to use either the restriction or interpolation (its transpose) 8912 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8913 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8914 8915 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8916 @*/ 8917 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8918 { 8919 PetscFunctionBegin; 8920 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8921 PetscFunctionReturn(PETSC_SUCCESS); 8922 } 8923 8924 /*@ 8925 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8926 8927 Neighbor-wise Collective 8928 8929 Input Parameters: 8930 + A - the matrix 8931 - x - the input dense matrix 8932 8933 Output Parameter: 8934 . y - the output dense matrix 8935 8936 Level: intermediate 8937 8938 Note: 8939 This allows one to use either the restriction or interpolation (its transpose) 8940 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8941 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8942 8943 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8944 @*/ 8945 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8946 { 8947 PetscFunctionBegin; 8948 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8949 PetscFunctionReturn(PETSC_SUCCESS); 8950 } 8951 8952 /*@ 8953 MatGetNullSpace - retrieves the null space of a matrix. 8954 8955 Logically Collective 8956 8957 Input Parameters: 8958 + mat - the matrix 8959 - nullsp - the null space object 8960 8961 Level: developer 8962 8963 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8964 @*/ 8965 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8966 { 8967 PetscFunctionBegin; 8968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8969 PetscAssertPointer(nullsp, 2); 8970 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8971 PetscFunctionReturn(PETSC_SUCCESS); 8972 } 8973 8974 /*@C 8975 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8976 8977 Logically Collective 8978 8979 Input Parameters: 8980 + n - the number of matrices 8981 - mat - the array of matrices 8982 8983 Output Parameters: 8984 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space 8985 8986 Level: developer 8987 8988 Note: 8989 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8990 8991 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8992 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8993 @*/ 8994 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8995 { 8996 PetscFunctionBegin; 8997 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8998 PetscAssertPointer(mat, 2); 8999 PetscAssertPointer(nullsp, 3); 9000 9001 PetscCall(PetscCalloc1(3 * n, nullsp)); 9002 for (PetscInt i = 0; i < n; i++) { 9003 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9004 (*nullsp)[i] = mat[i]->nullsp; 9005 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9006 (*nullsp)[n + i] = mat[i]->nearnullsp; 9007 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9008 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9009 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9010 } 9011 PetscFunctionReturn(PETSC_SUCCESS); 9012 } 9013 9014 /*@C 9015 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9016 9017 Logically Collective 9018 9019 Input Parameters: 9020 + n - the number of matrices 9021 . mat - the array of matrices 9022 - nullsp - an array of null spaces, `NULL` if the null space does not exist 9023 9024 Level: developer 9025 9026 Note: 9027 Call `MatGetNullSpaces()` to create `nullsp` 9028 9029 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9030 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9031 @*/ 9032 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9033 { 9034 PetscFunctionBegin; 9035 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9036 PetscAssertPointer(mat, 2); 9037 PetscAssertPointer(nullsp, 3); 9038 PetscAssertPointer(*nullsp, 3); 9039 9040 for (PetscInt i = 0; i < n; i++) { 9041 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9042 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9043 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9044 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9045 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9046 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9047 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9048 } 9049 PetscCall(PetscFree(*nullsp)); 9050 PetscFunctionReturn(PETSC_SUCCESS); 9051 } 9052 9053 /*@ 9054 MatSetNullSpace - attaches a null space to a matrix. 9055 9056 Logically Collective 9057 9058 Input Parameters: 9059 + mat - the matrix 9060 - nullsp - the null space object 9061 9062 Level: advanced 9063 9064 Notes: 9065 This null space is used by the `KSP` linear solvers to solve singular systems. 9066 9067 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` 9068 9069 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 9070 to zero but the linear system will still be solved in a least squares sense. 9071 9072 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9073 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)$. 9074 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 9075 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 9076 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$). 9077 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9078 9079 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9080 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9081 routine also automatically calls `MatSetTransposeNullSpace()`. 9082 9083 The user should call `MatNullSpaceDestroy()`. 9084 9085 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9086 `KSPSetPCSide()` 9087 @*/ 9088 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9089 { 9090 PetscFunctionBegin; 9091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9092 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9093 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9094 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9095 mat->nullsp = nullsp; 9096 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9097 PetscFunctionReturn(PETSC_SUCCESS); 9098 } 9099 9100 /*@ 9101 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9102 9103 Logically Collective 9104 9105 Input Parameters: 9106 + mat - the matrix 9107 - nullsp - the null space object 9108 9109 Level: developer 9110 9111 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9112 @*/ 9113 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9114 { 9115 PetscFunctionBegin; 9116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9117 PetscValidType(mat, 1); 9118 PetscAssertPointer(nullsp, 2); 9119 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9120 PetscFunctionReturn(PETSC_SUCCESS); 9121 } 9122 9123 /*@ 9124 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9125 9126 Logically Collective 9127 9128 Input Parameters: 9129 + mat - the matrix 9130 - nullsp - the null space object 9131 9132 Level: advanced 9133 9134 Notes: 9135 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9136 9137 See `MatSetNullSpace()` 9138 9139 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9140 @*/ 9141 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9142 { 9143 PetscFunctionBegin; 9144 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9145 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9146 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9147 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9148 mat->transnullsp = nullsp; 9149 PetscFunctionReturn(PETSC_SUCCESS); 9150 } 9151 9152 /*@ 9153 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9154 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9155 9156 Logically Collective 9157 9158 Input Parameters: 9159 + mat - the matrix 9160 - nullsp - the null space object 9161 9162 Level: advanced 9163 9164 Notes: 9165 Overwrites any previous near null space that may have been attached 9166 9167 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9168 9169 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9170 @*/ 9171 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9172 { 9173 PetscFunctionBegin; 9174 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9175 PetscValidType(mat, 1); 9176 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9177 MatCheckPreallocated(mat, 1); 9178 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9179 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9180 mat->nearnullsp = nullsp; 9181 PetscFunctionReturn(PETSC_SUCCESS); 9182 } 9183 9184 /*@ 9185 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9186 9187 Not Collective 9188 9189 Input Parameter: 9190 . mat - the matrix 9191 9192 Output Parameter: 9193 . nullsp - the null space object, `NULL` if not set 9194 9195 Level: advanced 9196 9197 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9198 @*/ 9199 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9200 { 9201 PetscFunctionBegin; 9202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9203 PetscValidType(mat, 1); 9204 PetscAssertPointer(nullsp, 2); 9205 MatCheckPreallocated(mat, 1); 9206 *nullsp = mat->nearnullsp; 9207 PetscFunctionReturn(PETSC_SUCCESS); 9208 } 9209 9210 /*@C 9211 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9212 9213 Collective 9214 9215 Input Parameters: 9216 + mat - the matrix 9217 . row - row/column permutation 9218 - info - information on desired factorization process 9219 9220 Level: developer 9221 9222 Notes: 9223 Probably really in-place only when level of fill is zero, otherwise allocates 9224 new space to store factored matrix and deletes previous memory. 9225 9226 Most users should employ the `KSP` interface for linear solvers 9227 instead of working directly with matrix algebra routines such as this. 9228 See, e.g., `KSPCreate()`. 9229 9230 Developer Note: 9231 The Fortran interface is not autogenerated as the 9232 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9233 9234 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9235 @*/ 9236 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9237 { 9238 PetscFunctionBegin; 9239 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9240 PetscValidType(mat, 1); 9241 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9242 PetscAssertPointer(info, 3); 9243 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9244 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9245 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9246 MatCheckPreallocated(mat, 1); 9247 PetscUseTypeMethod(mat, iccfactor, row, info); 9248 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9249 PetscFunctionReturn(PETSC_SUCCESS); 9250 } 9251 9252 /*@ 9253 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9254 ghosted ones. 9255 9256 Not Collective 9257 9258 Input Parameters: 9259 + mat - the matrix 9260 - diag - the diagonal values, including ghost ones 9261 9262 Level: developer 9263 9264 Notes: 9265 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9266 9267 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9268 9269 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9270 @*/ 9271 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9272 { 9273 PetscMPIInt size; 9274 9275 PetscFunctionBegin; 9276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9277 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9278 PetscValidType(mat, 1); 9279 9280 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9281 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9282 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9283 if (size == 1) { 9284 PetscInt n, m; 9285 PetscCall(VecGetSize(diag, &n)); 9286 PetscCall(MatGetSize(mat, NULL, &m)); 9287 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9288 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9289 } else { 9290 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9291 } 9292 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9293 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9294 PetscFunctionReturn(PETSC_SUCCESS); 9295 } 9296 9297 /*@ 9298 MatGetInertia - Gets the inertia from a factored matrix 9299 9300 Collective 9301 9302 Input Parameter: 9303 . mat - the matrix 9304 9305 Output Parameters: 9306 + nneg - number of negative eigenvalues 9307 . nzero - number of zero eigenvalues 9308 - npos - number of positive eigenvalues 9309 9310 Level: advanced 9311 9312 Note: 9313 Matrix must have been factored by `MatCholeskyFactor()` 9314 9315 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9316 @*/ 9317 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9318 { 9319 PetscFunctionBegin; 9320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9321 PetscValidType(mat, 1); 9322 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9324 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9325 PetscFunctionReturn(PETSC_SUCCESS); 9326 } 9327 9328 /*@C 9329 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9330 9331 Neighbor-wise Collective 9332 9333 Input Parameters: 9334 + mat - the factored matrix obtained with `MatGetFactor()` 9335 - b - the right-hand-side vectors 9336 9337 Output Parameter: 9338 . x - the result vectors 9339 9340 Level: developer 9341 9342 Note: 9343 The vectors `b` and `x` cannot be the same. I.e., one cannot 9344 call `MatSolves`(A,x,x). 9345 9346 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9347 @*/ 9348 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9349 { 9350 PetscFunctionBegin; 9351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9352 PetscValidType(mat, 1); 9353 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9354 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9355 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9356 9357 MatCheckPreallocated(mat, 1); 9358 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9359 PetscUseTypeMethod(mat, solves, b, x); 9360 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9361 PetscFunctionReturn(PETSC_SUCCESS); 9362 } 9363 9364 /*@ 9365 MatIsSymmetric - Test whether a matrix is symmetric 9366 9367 Collective 9368 9369 Input Parameters: 9370 + A - the matrix to test 9371 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9372 9373 Output Parameter: 9374 . flg - the result 9375 9376 Level: intermediate 9377 9378 Notes: 9379 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9380 9381 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9382 9383 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9384 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9385 9386 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9387 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9388 @*/ 9389 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9390 { 9391 PetscFunctionBegin; 9392 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9393 PetscAssertPointer(flg, 3); 9394 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9395 else { 9396 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9397 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9398 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9399 } 9400 PetscFunctionReturn(PETSC_SUCCESS); 9401 } 9402 9403 /*@ 9404 MatIsHermitian - Test whether a matrix is Hermitian 9405 9406 Collective 9407 9408 Input Parameters: 9409 + A - the matrix to test 9410 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9411 9412 Output Parameter: 9413 . flg - the result 9414 9415 Level: intermediate 9416 9417 Notes: 9418 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9419 9420 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9421 9422 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9423 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9424 9425 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9426 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9427 @*/ 9428 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9429 { 9430 PetscFunctionBegin; 9431 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9432 PetscAssertPointer(flg, 3); 9433 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9434 else { 9435 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9436 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9437 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9438 } 9439 PetscFunctionReturn(PETSC_SUCCESS); 9440 } 9441 9442 /*@ 9443 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9444 9445 Not Collective 9446 9447 Input Parameter: 9448 . A - the matrix to check 9449 9450 Output Parameters: 9451 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9452 - flg - the result (only valid if set is `PETSC_TRUE`) 9453 9454 Level: advanced 9455 9456 Notes: 9457 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9458 if you want it explicitly checked 9459 9460 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9461 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9462 9463 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9464 @*/ 9465 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9466 { 9467 PetscFunctionBegin; 9468 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9469 PetscAssertPointer(set, 2); 9470 PetscAssertPointer(flg, 3); 9471 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9472 *set = PETSC_TRUE; 9473 *flg = PetscBool3ToBool(A->symmetric); 9474 } else { 9475 *set = PETSC_FALSE; 9476 } 9477 PetscFunctionReturn(PETSC_SUCCESS); 9478 } 9479 9480 /*@ 9481 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9482 9483 Not Collective 9484 9485 Input Parameter: 9486 . A - the matrix to check 9487 9488 Output Parameters: 9489 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9490 - flg - the result (only valid if set is `PETSC_TRUE`) 9491 9492 Level: advanced 9493 9494 Notes: 9495 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9496 9497 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9498 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9499 9500 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9501 @*/ 9502 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9503 { 9504 PetscFunctionBegin; 9505 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9506 PetscAssertPointer(set, 2); 9507 PetscAssertPointer(flg, 3); 9508 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9509 *set = PETSC_TRUE; 9510 *flg = PetscBool3ToBool(A->spd); 9511 } else { 9512 *set = PETSC_FALSE; 9513 } 9514 PetscFunctionReturn(PETSC_SUCCESS); 9515 } 9516 9517 /*@ 9518 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9519 9520 Not Collective 9521 9522 Input Parameter: 9523 . A - the matrix to check 9524 9525 Output Parameters: 9526 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9527 - flg - the result (only valid if set is `PETSC_TRUE`) 9528 9529 Level: advanced 9530 9531 Notes: 9532 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9533 if you want it explicitly checked 9534 9535 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9536 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9537 9538 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9539 @*/ 9540 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9541 { 9542 PetscFunctionBegin; 9543 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9544 PetscAssertPointer(set, 2); 9545 PetscAssertPointer(flg, 3); 9546 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9547 *set = PETSC_TRUE; 9548 *flg = PetscBool3ToBool(A->hermitian); 9549 } else { 9550 *set = PETSC_FALSE; 9551 } 9552 PetscFunctionReturn(PETSC_SUCCESS); 9553 } 9554 9555 /*@ 9556 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9557 9558 Collective 9559 9560 Input Parameter: 9561 . A - the matrix to test 9562 9563 Output Parameter: 9564 . flg - the result 9565 9566 Level: intermediate 9567 9568 Notes: 9569 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9570 9571 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 9572 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9573 9574 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9575 @*/ 9576 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9577 { 9578 PetscFunctionBegin; 9579 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9580 PetscAssertPointer(flg, 2); 9581 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9582 *flg = PetscBool3ToBool(A->structurally_symmetric); 9583 } else { 9584 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9585 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9586 } 9587 PetscFunctionReturn(PETSC_SUCCESS); 9588 } 9589 9590 /*@ 9591 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9592 9593 Not Collective 9594 9595 Input Parameter: 9596 . A - the matrix to check 9597 9598 Output Parameters: 9599 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9600 - flg - the result (only valid if set is PETSC_TRUE) 9601 9602 Level: advanced 9603 9604 Notes: 9605 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 9606 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9607 9608 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9609 9610 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9611 @*/ 9612 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9613 { 9614 PetscFunctionBegin; 9615 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9616 PetscAssertPointer(set, 2); 9617 PetscAssertPointer(flg, 3); 9618 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9619 *set = PETSC_TRUE; 9620 *flg = PetscBool3ToBool(A->structurally_symmetric); 9621 } else { 9622 *set = PETSC_FALSE; 9623 } 9624 PetscFunctionReturn(PETSC_SUCCESS); 9625 } 9626 9627 /*@ 9628 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9629 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9630 9631 Not Collective 9632 9633 Input Parameter: 9634 . mat - the matrix 9635 9636 Output Parameters: 9637 + nstash - the size of the stash 9638 . reallocs - the number of additional mallocs incurred. 9639 . bnstash - the size of the block stash 9640 - breallocs - the number of additional mallocs incurred.in the block stash 9641 9642 Level: advanced 9643 9644 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9645 @*/ 9646 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9647 { 9648 PetscFunctionBegin; 9649 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9650 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9651 PetscFunctionReturn(PETSC_SUCCESS); 9652 } 9653 9654 /*@C 9655 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9656 parallel layout, `PetscLayout` for rows and columns 9657 9658 Collective 9659 9660 Input Parameter: 9661 . mat - the matrix 9662 9663 Output Parameters: 9664 + right - (optional) vector that the matrix can be multiplied against 9665 - left - (optional) vector that the matrix vector product can be stored in 9666 9667 Level: advanced 9668 9669 Notes: 9670 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()`. 9671 9672 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9673 9674 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9675 @*/ 9676 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9677 { 9678 PetscFunctionBegin; 9679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9680 PetscValidType(mat, 1); 9681 if (mat->ops->getvecs) { 9682 PetscUseTypeMethod(mat, getvecs, right, left); 9683 } else { 9684 if (right) { 9685 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9686 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9687 PetscCall(VecSetType(*right, mat->defaultvectype)); 9688 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9689 if (mat->boundtocpu && mat->bindingpropagates) { 9690 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9691 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9692 } 9693 #endif 9694 } 9695 if (left) { 9696 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9697 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9698 PetscCall(VecSetType(*left, mat->defaultvectype)); 9699 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9700 if (mat->boundtocpu && mat->bindingpropagates) { 9701 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9702 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9703 } 9704 #endif 9705 } 9706 } 9707 PetscFunctionReturn(PETSC_SUCCESS); 9708 } 9709 9710 /*@C 9711 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9712 with default values. 9713 9714 Not Collective 9715 9716 Input Parameter: 9717 . info - the `MatFactorInfo` data structure 9718 9719 Level: developer 9720 9721 Notes: 9722 The solvers are generally used through the `KSP` and `PC` objects, for example 9723 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9724 9725 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9726 9727 Developer Note: 9728 The Fortran interface is not autogenerated as the 9729 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9730 9731 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9732 @*/ 9733 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9734 { 9735 PetscFunctionBegin; 9736 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9737 PetscFunctionReturn(PETSC_SUCCESS); 9738 } 9739 9740 /*@ 9741 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9742 9743 Collective 9744 9745 Input Parameters: 9746 + mat - the factored matrix 9747 - is - the index set defining the Schur indices (0-based) 9748 9749 Level: advanced 9750 9751 Notes: 9752 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9753 9754 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9755 9756 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9757 9758 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9759 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9760 @*/ 9761 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9762 { 9763 PetscErrorCode (*f)(Mat, IS); 9764 9765 PetscFunctionBegin; 9766 PetscValidType(mat, 1); 9767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9768 PetscValidType(is, 2); 9769 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9770 PetscCheckSameComm(mat, 1, is, 2); 9771 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9772 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9773 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9774 PetscCall(MatDestroy(&mat->schur)); 9775 PetscCall((*f)(mat, is)); 9776 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9777 PetscFunctionReturn(PETSC_SUCCESS); 9778 } 9779 9780 /*@ 9781 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9782 9783 Logically Collective 9784 9785 Input Parameters: 9786 + F - the factored matrix obtained by calling `MatGetFactor()` 9787 . S - location where to return the Schur complement, can be `NULL` 9788 - status - the status of the Schur complement matrix, can be `NULL` 9789 9790 Level: advanced 9791 9792 Notes: 9793 You must call `MatFactorSetSchurIS()` before calling this routine. 9794 9795 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9796 9797 The routine provides a copy of the Schur matrix stored within the solver data structures. 9798 The caller must destroy the object when it is no longer needed. 9799 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9800 9801 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) 9802 9803 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9804 9805 Developer Note: 9806 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9807 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9808 9809 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9810 @*/ 9811 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9812 { 9813 PetscFunctionBegin; 9814 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9815 if (S) PetscAssertPointer(S, 2); 9816 if (status) PetscAssertPointer(status, 3); 9817 if (S) { 9818 PetscErrorCode (*f)(Mat, Mat *); 9819 9820 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9821 if (f) { 9822 PetscCall((*f)(F, S)); 9823 } else { 9824 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9825 } 9826 } 9827 if (status) *status = F->schur_status; 9828 PetscFunctionReturn(PETSC_SUCCESS); 9829 } 9830 9831 /*@ 9832 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9833 9834 Logically Collective 9835 9836 Input Parameters: 9837 + F - the factored matrix obtained by calling `MatGetFactor()` 9838 . S - location where to return the Schur complement, can be `NULL` 9839 - status - the status of the Schur complement matrix, can be `NULL` 9840 9841 Level: advanced 9842 9843 Notes: 9844 You must call `MatFactorSetSchurIS()` before calling this routine. 9845 9846 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9847 9848 The routine returns a the Schur Complement stored within the data structures of the solver. 9849 9850 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9851 9852 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9853 9854 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9855 9856 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9857 9858 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9859 @*/ 9860 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9861 { 9862 PetscFunctionBegin; 9863 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9864 if (S) { 9865 PetscAssertPointer(S, 2); 9866 *S = F->schur; 9867 } 9868 if (status) { 9869 PetscAssertPointer(status, 3); 9870 *status = F->schur_status; 9871 } 9872 PetscFunctionReturn(PETSC_SUCCESS); 9873 } 9874 9875 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9876 { 9877 Mat S = F->schur; 9878 9879 PetscFunctionBegin; 9880 switch (F->schur_status) { 9881 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9882 case MAT_FACTOR_SCHUR_INVERTED: 9883 if (S) { 9884 S->ops->solve = NULL; 9885 S->ops->matsolve = NULL; 9886 S->ops->solvetranspose = NULL; 9887 S->ops->matsolvetranspose = NULL; 9888 S->ops->solveadd = NULL; 9889 S->ops->solvetransposeadd = NULL; 9890 S->factortype = MAT_FACTOR_NONE; 9891 PetscCall(PetscFree(S->solvertype)); 9892 } 9893 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9894 break; 9895 default: 9896 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9897 } 9898 PetscFunctionReturn(PETSC_SUCCESS); 9899 } 9900 9901 /*@ 9902 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9903 9904 Logically Collective 9905 9906 Input Parameters: 9907 + F - the factored matrix obtained by calling `MatGetFactor()` 9908 . S - location where the Schur complement is stored 9909 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9910 9911 Level: advanced 9912 9913 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9914 @*/ 9915 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9916 { 9917 PetscFunctionBegin; 9918 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9919 if (S) { 9920 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9921 *S = NULL; 9922 } 9923 F->schur_status = status; 9924 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9925 PetscFunctionReturn(PETSC_SUCCESS); 9926 } 9927 9928 /*@ 9929 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9930 9931 Logically Collective 9932 9933 Input Parameters: 9934 + F - the factored matrix obtained by calling `MatGetFactor()` 9935 . rhs - location where the right-hand side of the Schur complement system is stored 9936 - sol - location where the solution of the Schur complement system has to be returned 9937 9938 Level: advanced 9939 9940 Notes: 9941 The sizes of the vectors should match the size of the Schur complement 9942 9943 Must be called after `MatFactorSetSchurIS()` 9944 9945 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9946 @*/ 9947 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9948 { 9949 PetscFunctionBegin; 9950 PetscValidType(F, 1); 9951 PetscValidType(rhs, 2); 9952 PetscValidType(sol, 3); 9953 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9954 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9955 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9956 PetscCheckSameComm(F, 1, rhs, 2); 9957 PetscCheckSameComm(F, 1, sol, 3); 9958 PetscCall(MatFactorFactorizeSchurComplement(F)); 9959 switch (F->schur_status) { 9960 case MAT_FACTOR_SCHUR_FACTORED: 9961 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9962 break; 9963 case MAT_FACTOR_SCHUR_INVERTED: 9964 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9965 break; 9966 default: 9967 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9968 } 9969 PetscFunctionReturn(PETSC_SUCCESS); 9970 } 9971 9972 /*@ 9973 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9974 9975 Logically Collective 9976 9977 Input Parameters: 9978 + F - the factored matrix obtained by calling `MatGetFactor()` 9979 . rhs - location where the right-hand side of the Schur complement system is stored 9980 - sol - location where the solution of the Schur complement system has to be returned 9981 9982 Level: advanced 9983 9984 Notes: 9985 The sizes of the vectors should match the size of the Schur complement 9986 9987 Must be called after `MatFactorSetSchurIS()` 9988 9989 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9990 @*/ 9991 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9992 { 9993 PetscFunctionBegin; 9994 PetscValidType(F, 1); 9995 PetscValidType(rhs, 2); 9996 PetscValidType(sol, 3); 9997 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9998 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9999 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10000 PetscCheckSameComm(F, 1, rhs, 2); 10001 PetscCheckSameComm(F, 1, sol, 3); 10002 PetscCall(MatFactorFactorizeSchurComplement(F)); 10003 switch (F->schur_status) { 10004 case MAT_FACTOR_SCHUR_FACTORED: 10005 PetscCall(MatSolve(F->schur, rhs, sol)); 10006 break; 10007 case MAT_FACTOR_SCHUR_INVERTED: 10008 PetscCall(MatMult(F->schur, rhs, sol)); 10009 break; 10010 default: 10011 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10012 } 10013 PetscFunctionReturn(PETSC_SUCCESS); 10014 } 10015 10016 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10017 #if PetscDefined(HAVE_CUDA) 10018 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10019 #endif 10020 10021 /* Schur status updated in the interface */ 10022 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10023 { 10024 Mat S = F->schur; 10025 10026 PetscFunctionBegin; 10027 if (S) { 10028 PetscMPIInt size; 10029 PetscBool isdense, isdensecuda; 10030 10031 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10032 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10033 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10034 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10035 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10036 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10037 if (isdense) { 10038 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10039 } else if (isdensecuda) { 10040 #if defined(PETSC_HAVE_CUDA) 10041 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10042 #endif 10043 } 10044 // HIP?????????????? 10045 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10046 } 10047 PetscFunctionReturn(PETSC_SUCCESS); 10048 } 10049 10050 /*@ 10051 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10052 10053 Logically Collective 10054 10055 Input Parameter: 10056 . F - the factored matrix obtained by calling `MatGetFactor()` 10057 10058 Level: advanced 10059 10060 Notes: 10061 Must be called after `MatFactorSetSchurIS()`. 10062 10063 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10064 10065 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10066 @*/ 10067 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10068 { 10069 PetscFunctionBegin; 10070 PetscValidType(F, 1); 10071 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10072 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10073 PetscCall(MatFactorFactorizeSchurComplement(F)); 10074 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10075 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10076 PetscFunctionReturn(PETSC_SUCCESS); 10077 } 10078 10079 /*@ 10080 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10081 10082 Logically Collective 10083 10084 Input Parameter: 10085 . F - the factored matrix obtained by calling `MatGetFactor()` 10086 10087 Level: advanced 10088 10089 Note: 10090 Must be called after `MatFactorSetSchurIS()` 10091 10092 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10093 @*/ 10094 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10095 { 10096 MatFactorInfo info; 10097 10098 PetscFunctionBegin; 10099 PetscValidType(F, 1); 10100 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10101 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10102 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10103 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10104 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10105 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10106 } else { 10107 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10108 } 10109 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10110 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10111 PetscFunctionReturn(PETSC_SUCCESS); 10112 } 10113 10114 /*@ 10115 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10116 10117 Neighbor-wise Collective 10118 10119 Input Parameters: 10120 + A - the matrix 10121 . P - the projection matrix 10122 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10123 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10124 if the result is a dense matrix this is irrelevant 10125 10126 Output Parameter: 10127 . C - the product matrix 10128 10129 Level: intermediate 10130 10131 Notes: 10132 C will be created and must be destroyed by the user with `MatDestroy()`. 10133 10134 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10135 10136 Developer Note: 10137 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10138 10139 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10140 @*/ 10141 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10142 { 10143 PetscFunctionBegin; 10144 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10145 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10146 10147 if (scall == MAT_INITIAL_MATRIX) { 10148 PetscCall(MatProductCreate(A, P, NULL, C)); 10149 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10150 PetscCall(MatProductSetAlgorithm(*C, "default")); 10151 PetscCall(MatProductSetFill(*C, fill)); 10152 10153 (*C)->product->api_user = PETSC_TRUE; 10154 PetscCall(MatProductSetFromOptions(*C)); 10155 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); 10156 PetscCall(MatProductSymbolic(*C)); 10157 } else { /* scall == MAT_REUSE_MATRIX */ 10158 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10159 } 10160 10161 PetscCall(MatProductNumeric(*C)); 10162 (*C)->symmetric = A->symmetric; 10163 (*C)->spd = A->spd; 10164 PetscFunctionReturn(PETSC_SUCCESS); 10165 } 10166 10167 /*@ 10168 MatRARt - Creates the matrix product $C = R * A * R^T$ 10169 10170 Neighbor-wise Collective 10171 10172 Input Parameters: 10173 + A - the matrix 10174 . R - the projection matrix 10175 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10176 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10177 if the result is a dense matrix this is irrelevant 10178 10179 Output Parameter: 10180 . C - the product matrix 10181 10182 Level: intermediate 10183 10184 Notes: 10185 C will be created and must be destroyed by the user with `MatDestroy()`. 10186 10187 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10188 10189 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10190 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10191 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10192 We recommend using MatPtAP(). 10193 10194 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10195 @*/ 10196 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10197 { 10198 PetscFunctionBegin; 10199 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10200 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10201 10202 if (scall == MAT_INITIAL_MATRIX) { 10203 PetscCall(MatProductCreate(A, R, NULL, C)); 10204 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10205 PetscCall(MatProductSetAlgorithm(*C, "default")); 10206 PetscCall(MatProductSetFill(*C, fill)); 10207 10208 (*C)->product->api_user = PETSC_TRUE; 10209 PetscCall(MatProductSetFromOptions(*C)); 10210 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); 10211 PetscCall(MatProductSymbolic(*C)); 10212 } else { /* scall == MAT_REUSE_MATRIX */ 10213 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10214 } 10215 10216 PetscCall(MatProductNumeric(*C)); 10217 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10218 PetscFunctionReturn(PETSC_SUCCESS); 10219 } 10220 10221 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10222 { 10223 PetscBool flg = PETSC_TRUE; 10224 10225 PetscFunctionBegin; 10226 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10227 if (scall == MAT_INITIAL_MATRIX) { 10228 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10229 PetscCall(MatProductCreate(A, B, NULL, C)); 10230 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10231 PetscCall(MatProductSetFill(*C, fill)); 10232 } else { /* scall == MAT_REUSE_MATRIX */ 10233 Mat_Product *product = (*C)->product; 10234 10235 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10236 if (flg && product && product->type != ptype) { 10237 PetscCall(MatProductClear(*C)); 10238 product = NULL; 10239 } 10240 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10241 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10242 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10243 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10244 product = (*C)->product; 10245 product->fill = fill; 10246 product->clear = PETSC_TRUE; 10247 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10248 flg = PETSC_FALSE; 10249 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10250 } 10251 } 10252 if (flg) { 10253 (*C)->product->api_user = PETSC_TRUE; 10254 PetscCall(MatProductSetType(*C, ptype)); 10255 PetscCall(MatProductSetFromOptions(*C)); 10256 PetscCall(MatProductSymbolic(*C)); 10257 } 10258 PetscCall(MatProductNumeric(*C)); 10259 PetscFunctionReturn(PETSC_SUCCESS); 10260 } 10261 10262 /*@ 10263 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10264 10265 Neighbor-wise Collective 10266 10267 Input Parameters: 10268 + A - the left matrix 10269 . B - the right matrix 10270 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10271 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10272 if the result is a dense matrix this is irrelevant 10273 10274 Output Parameter: 10275 . C - the product matrix 10276 10277 Notes: 10278 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10279 10280 `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 10281 call to this function with `MAT_INITIAL_MATRIX`. 10282 10283 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10284 10285 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`, 10286 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10287 10288 Example of Usage: 10289 .vb 10290 MatProductCreate(A,B,NULL,&C); 10291 MatProductSetType(C,MATPRODUCT_AB); 10292 MatProductSymbolic(C); 10293 MatProductNumeric(C); // compute C=A * B 10294 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10295 MatProductNumeric(C); 10296 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10297 MatProductNumeric(C); 10298 .ve 10299 10300 Level: intermediate 10301 10302 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10303 @*/ 10304 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10305 { 10306 PetscFunctionBegin; 10307 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10308 PetscFunctionReturn(PETSC_SUCCESS); 10309 } 10310 10311 /*@ 10312 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10313 10314 Neighbor-wise Collective 10315 10316 Input Parameters: 10317 + A - the left matrix 10318 . B - the right matrix 10319 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10320 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10321 10322 Output Parameter: 10323 . C - the product matrix 10324 10325 Options Database Key: 10326 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10327 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10328 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10329 10330 Level: intermediate 10331 10332 Notes: 10333 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10334 10335 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10336 10337 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10338 actually needed. 10339 10340 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10341 and for pairs of `MATMPIDENSE` matrices. 10342 10343 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10344 10345 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10346 @*/ 10347 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10348 { 10349 PetscFunctionBegin; 10350 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10351 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10352 PetscFunctionReturn(PETSC_SUCCESS); 10353 } 10354 10355 /*@ 10356 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10357 10358 Neighbor-wise Collective 10359 10360 Input Parameters: 10361 + A - the left matrix 10362 . B - the right matrix 10363 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10364 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10365 10366 Output Parameter: 10367 . C - the product matrix 10368 10369 Level: intermediate 10370 10371 Notes: 10372 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10373 10374 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10375 10376 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10377 10378 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10379 actually needed. 10380 10381 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10382 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10383 10384 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10385 @*/ 10386 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10387 { 10388 PetscFunctionBegin; 10389 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10390 PetscFunctionReturn(PETSC_SUCCESS); 10391 } 10392 10393 /*@ 10394 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10395 10396 Neighbor-wise Collective 10397 10398 Input Parameters: 10399 + A - the left matrix 10400 . B - the middle matrix 10401 . C - the right matrix 10402 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10403 - 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 10404 if the result is a dense matrix this is irrelevant 10405 10406 Output Parameter: 10407 . D - the product matrix 10408 10409 Level: intermediate 10410 10411 Notes: 10412 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10413 10414 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10415 10416 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10417 10418 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10419 actually needed. 10420 10421 If you have many matrices with the same non-zero structure to multiply, you 10422 should use `MAT_REUSE_MATRIX` in all calls but the first 10423 10424 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10425 @*/ 10426 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10427 { 10428 PetscFunctionBegin; 10429 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10430 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10431 10432 if (scall == MAT_INITIAL_MATRIX) { 10433 PetscCall(MatProductCreate(A, B, C, D)); 10434 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10435 PetscCall(MatProductSetAlgorithm(*D, "default")); 10436 PetscCall(MatProductSetFill(*D, fill)); 10437 10438 (*D)->product->api_user = PETSC_TRUE; 10439 PetscCall(MatProductSetFromOptions(*D)); 10440 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, 10441 ((PetscObject)C)->type_name); 10442 PetscCall(MatProductSymbolic(*D)); 10443 } else { /* user may change input matrices when REUSE */ 10444 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10445 } 10446 PetscCall(MatProductNumeric(*D)); 10447 PetscFunctionReturn(PETSC_SUCCESS); 10448 } 10449 10450 /*@ 10451 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10452 10453 Collective 10454 10455 Input Parameters: 10456 + mat - the matrix 10457 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10458 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10459 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10460 10461 Output Parameter: 10462 . matredundant - redundant matrix 10463 10464 Level: advanced 10465 10466 Notes: 10467 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10468 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10469 10470 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10471 calling it. 10472 10473 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10474 10475 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10476 @*/ 10477 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10478 { 10479 MPI_Comm comm; 10480 PetscMPIInt size; 10481 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10482 Mat_Redundant *redund = NULL; 10483 PetscSubcomm psubcomm = NULL; 10484 MPI_Comm subcomm_in = subcomm; 10485 Mat *matseq; 10486 IS isrow, iscol; 10487 PetscBool newsubcomm = PETSC_FALSE; 10488 10489 PetscFunctionBegin; 10490 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10491 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10492 PetscAssertPointer(*matredundant, 5); 10493 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10494 } 10495 10496 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10497 if (size == 1 || nsubcomm == 1) { 10498 if (reuse == MAT_INITIAL_MATRIX) { 10499 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10500 } else { 10501 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"); 10502 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10503 } 10504 PetscFunctionReturn(PETSC_SUCCESS); 10505 } 10506 10507 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10508 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10509 MatCheckPreallocated(mat, 1); 10510 10511 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10512 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10513 /* create psubcomm, then get subcomm */ 10514 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10515 PetscCallMPI(MPI_Comm_size(comm, &size)); 10516 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10517 10518 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10519 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10520 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10521 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10522 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10523 newsubcomm = PETSC_TRUE; 10524 PetscCall(PetscSubcommDestroy(&psubcomm)); 10525 } 10526 10527 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10528 if (reuse == MAT_INITIAL_MATRIX) { 10529 mloc_sub = PETSC_DECIDE; 10530 nloc_sub = PETSC_DECIDE; 10531 if (bs < 1) { 10532 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10533 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10534 } else { 10535 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10536 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10537 } 10538 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10539 rstart = rend - mloc_sub; 10540 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10541 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10542 PetscCall(ISSetIdentity(iscol)); 10543 } else { /* reuse == MAT_REUSE_MATRIX */ 10544 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"); 10545 /* retrieve subcomm */ 10546 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10547 redund = (*matredundant)->redundant; 10548 isrow = redund->isrow; 10549 iscol = redund->iscol; 10550 matseq = redund->matseq; 10551 } 10552 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10553 10554 /* get matredundant over subcomm */ 10555 if (reuse == MAT_INITIAL_MATRIX) { 10556 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10557 10558 /* create a supporting struct and attach it to C for reuse */ 10559 PetscCall(PetscNew(&redund)); 10560 (*matredundant)->redundant = redund; 10561 redund->isrow = isrow; 10562 redund->iscol = iscol; 10563 redund->matseq = matseq; 10564 if (newsubcomm) { 10565 redund->subcomm = subcomm; 10566 } else { 10567 redund->subcomm = MPI_COMM_NULL; 10568 } 10569 } else { 10570 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10571 } 10572 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10573 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10574 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10575 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10576 } 10577 #endif 10578 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10579 PetscFunctionReturn(PETSC_SUCCESS); 10580 } 10581 10582 /*@C 10583 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10584 a given `Mat`. Each submatrix can span multiple procs. 10585 10586 Collective 10587 10588 Input Parameters: 10589 + mat - the matrix 10590 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10591 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10592 10593 Output Parameter: 10594 . subMat - parallel sub-matrices each spanning a given `subcomm` 10595 10596 Level: advanced 10597 10598 Notes: 10599 The submatrix partition across processors is dictated by `subComm` a 10600 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10601 is not restricted to be grouped with consecutive original MPI processes. 10602 10603 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10604 map directly to the layout of the original matrix [wrt the local 10605 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10606 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10607 the `subMat`. However the offDiagMat looses some columns - and this is 10608 reconstructed with `MatSetValues()` 10609 10610 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10611 10612 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10613 @*/ 10614 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10615 { 10616 PetscMPIInt commsize, subCommSize; 10617 10618 PetscFunctionBegin; 10619 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10620 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10621 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10622 10623 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"); 10624 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10625 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10626 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10627 PetscFunctionReturn(PETSC_SUCCESS); 10628 } 10629 10630 /*@ 10631 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10632 10633 Not Collective 10634 10635 Input Parameters: 10636 + mat - matrix to extract local submatrix from 10637 . isrow - local row indices for submatrix 10638 - iscol - local column indices for submatrix 10639 10640 Output Parameter: 10641 . submat - the submatrix 10642 10643 Level: intermediate 10644 10645 Notes: 10646 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10647 10648 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10649 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10650 10651 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10652 `MatSetValuesBlockedLocal()` will also be implemented. 10653 10654 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10655 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10656 10657 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10658 @*/ 10659 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10660 { 10661 PetscFunctionBegin; 10662 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10663 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10664 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10665 PetscCheckSameComm(isrow, 2, iscol, 3); 10666 PetscAssertPointer(submat, 4); 10667 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10668 10669 if (mat->ops->getlocalsubmatrix) { 10670 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10671 } else { 10672 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10673 } 10674 PetscFunctionReturn(PETSC_SUCCESS); 10675 } 10676 10677 /*@ 10678 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10679 10680 Not Collective 10681 10682 Input Parameters: 10683 + mat - matrix to extract local submatrix from 10684 . isrow - local row indices for submatrix 10685 . iscol - local column indices for submatrix 10686 - submat - the submatrix 10687 10688 Level: intermediate 10689 10690 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10691 @*/ 10692 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10693 { 10694 PetscFunctionBegin; 10695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10696 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10697 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10698 PetscCheckSameComm(isrow, 2, iscol, 3); 10699 PetscAssertPointer(submat, 4); 10700 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10701 10702 if (mat->ops->restorelocalsubmatrix) { 10703 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10704 } else { 10705 PetscCall(MatDestroy(submat)); 10706 } 10707 *submat = NULL; 10708 PetscFunctionReturn(PETSC_SUCCESS); 10709 } 10710 10711 /*@ 10712 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10713 10714 Collective 10715 10716 Input Parameter: 10717 . mat - the matrix 10718 10719 Output Parameter: 10720 . is - if any rows have zero diagonals this contains the list of them 10721 10722 Level: developer 10723 10724 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10725 @*/ 10726 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10727 { 10728 PetscFunctionBegin; 10729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10730 PetscValidType(mat, 1); 10731 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10733 10734 if (!mat->ops->findzerodiagonals) { 10735 Vec diag; 10736 const PetscScalar *a; 10737 PetscInt *rows; 10738 PetscInt rStart, rEnd, r, nrow = 0; 10739 10740 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10741 PetscCall(MatGetDiagonal(mat, diag)); 10742 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10743 PetscCall(VecGetArrayRead(diag, &a)); 10744 for (r = 0; r < rEnd - rStart; ++r) 10745 if (a[r] == 0.0) ++nrow; 10746 PetscCall(PetscMalloc1(nrow, &rows)); 10747 nrow = 0; 10748 for (r = 0; r < rEnd - rStart; ++r) 10749 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10750 PetscCall(VecRestoreArrayRead(diag, &a)); 10751 PetscCall(VecDestroy(&diag)); 10752 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10753 } else { 10754 PetscUseTypeMethod(mat, findzerodiagonals, is); 10755 } 10756 PetscFunctionReturn(PETSC_SUCCESS); 10757 } 10758 10759 /*@ 10760 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10761 10762 Collective 10763 10764 Input Parameter: 10765 . mat - the matrix 10766 10767 Output Parameter: 10768 . is - contains the list of rows with off block diagonal entries 10769 10770 Level: developer 10771 10772 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10773 @*/ 10774 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10775 { 10776 PetscFunctionBegin; 10777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10778 PetscValidType(mat, 1); 10779 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10780 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10781 10782 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10783 PetscFunctionReturn(PETSC_SUCCESS); 10784 } 10785 10786 /*@C 10787 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10788 10789 Collective; No Fortran Support 10790 10791 Input Parameter: 10792 . mat - the matrix 10793 10794 Output Parameter: 10795 . values - the block inverses in column major order (FORTRAN-like) 10796 10797 Level: advanced 10798 10799 Notes: 10800 The size of the blocks is determined by the block size of the matrix. 10801 10802 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10803 10804 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10805 10806 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10807 @*/ 10808 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10809 { 10810 PetscFunctionBegin; 10811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10812 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10813 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10814 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10815 PetscFunctionReturn(PETSC_SUCCESS); 10816 } 10817 10818 /*@ 10819 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10820 10821 Collective; No Fortran Support 10822 10823 Input Parameters: 10824 + mat - the matrix 10825 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10826 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10827 10828 Output Parameter: 10829 . values - the block inverses in column major order (FORTRAN-like) 10830 10831 Level: advanced 10832 10833 Notes: 10834 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10835 10836 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10837 10838 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10839 @*/ 10840 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10841 { 10842 PetscFunctionBegin; 10843 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10844 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10845 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10846 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10847 PetscFunctionReturn(PETSC_SUCCESS); 10848 } 10849 10850 /*@ 10851 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10852 10853 Collective 10854 10855 Input Parameters: 10856 + A - the matrix 10857 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10858 10859 Level: advanced 10860 10861 Note: 10862 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10863 10864 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10865 @*/ 10866 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10867 { 10868 const PetscScalar *vals; 10869 PetscInt *dnnz; 10870 PetscInt m, rstart, rend, bs, i, j; 10871 10872 PetscFunctionBegin; 10873 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10874 PetscCall(MatGetBlockSize(A, &bs)); 10875 PetscCall(MatGetLocalSize(A, &m, NULL)); 10876 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10877 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10878 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10879 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10880 PetscCall(PetscFree(dnnz)); 10881 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10882 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10883 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10884 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10885 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10886 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10887 PetscFunctionReturn(PETSC_SUCCESS); 10888 } 10889 10890 /*@C 10891 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10892 via `MatTransposeColoringCreate()`. 10893 10894 Collective 10895 10896 Input Parameter: 10897 . c - coloring context 10898 10899 Level: intermediate 10900 10901 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10902 @*/ 10903 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10904 { 10905 MatTransposeColoring matcolor = *c; 10906 10907 PetscFunctionBegin; 10908 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10909 if (--((PetscObject)matcolor)->refct > 0) { 10910 matcolor = NULL; 10911 PetscFunctionReturn(PETSC_SUCCESS); 10912 } 10913 10914 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10915 PetscCall(PetscFree(matcolor->rows)); 10916 PetscCall(PetscFree(matcolor->den2sp)); 10917 PetscCall(PetscFree(matcolor->colorforcol)); 10918 PetscCall(PetscFree(matcolor->columns)); 10919 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10920 PetscCall(PetscHeaderDestroy(c)); 10921 PetscFunctionReturn(PETSC_SUCCESS); 10922 } 10923 10924 /*@ 10925 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10926 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10927 `MatTransposeColoring` to sparse `B`. 10928 10929 Collective 10930 10931 Input Parameters: 10932 + coloring - coloring context created with `MatTransposeColoringCreate()` 10933 - B - sparse matrix 10934 10935 Output Parameter: 10936 . Btdense - dense matrix $B^T$ 10937 10938 Level: developer 10939 10940 Note: 10941 These are used internally for some implementations of `MatRARt()` 10942 10943 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10944 @*/ 10945 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10946 { 10947 PetscFunctionBegin; 10948 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10949 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10950 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10951 10952 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10953 PetscFunctionReturn(PETSC_SUCCESS); 10954 } 10955 10956 /*@ 10957 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10958 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10959 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10960 $C_{sp}$ from $C_{den}$. 10961 10962 Collective 10963 10964 Input Parameters: 10965 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10966 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10967 10968 Output Parameter: 10969 . Csp - sparse matrix 10970 10971 Level: developer 10972 10973 Note: 10974 These are used internally for some implementations of `MatRARt()` 10975 10976 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10977 @*/ 10978 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10979 { 10980 PetscFunctionBegin; 10981 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10982 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10983 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10984 10985 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10986 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10987 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10988 PetscFunctionReturn(PETSC_SUCCESS); 10989 } 10990 10991 /*@ 10992 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10993 10994 Collective 10995 10996 Input Parameters: 10997 + mat - the matrix product C 10998 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10999 11000 Output Parameter: 11001 . color - the new coloring context 11002 11003 Level: intermediate 11004 11005 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11006 `MatTransColoringApplyDenToSp()` 11007 @*/ 11008 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11009 { 11010 MatTransposeColoring c; 11011 MPI_Comm comm; 11012 11013 PetscFunctionBegin; 11014 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11015 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11016 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11017 11018 c->ctype = iscoloring->ctype; 11019 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11020 11021 *color = c; 11022 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11023 PetscFunctionReturn(PETSC_SUCCESS); 11024 } 11025 11026 /*@ 11027 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11028 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11029 11030 Not Collective 11031 11032 Input Parameter: 11033 . mat - the matrix 11034 11035 Output Parameter: 11036 . state - the current state 11037 11038 Level: intermediate 11039 11040 Notes: 11041 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11042 different matrices 11043 11044 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11045 11046 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11047 11048 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11049 @*/ 11050 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11051 { 11052 PetscFunctionBegin; 11053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11054 *state = mat->nonzerostate; 11055 PetscFunctionReturn(PETSC_SUCCESS); 11056 } 11057 11058 /*@ 11059 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11060 matrices from each processor 11061 11062 Collective 11063 11064 Input Parameters: 11065 + comm - the communicators the parallel matrix will live on 11066 . seqmat - the input sequential matrices 11067 . n - number of local columns (or `PETSC_DECIDE`) 11068 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11069 11070 Output Parameter: 11071 . mpimat - the parallel matrix generated 11072 11073 Level: developer 11074 11075 Note: 11076 The number of columns of the matrix in EACH processor MUST be the same. 11077 11078 .seealso: [](ch_matrices), `Mat` 11079 @*/ 11080 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11081 { 11082 PetscMPIInt size; 11083 11084 PetscFunctionBegin; 11085 PetscCallMPI(MPI_Comm_size(comm, &size)); 11086 if (size == 1) { 11087 if (reuse == MAT_INITIAL_MATRIX) { 11088 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11089 } else { 11090 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11091 } 11092 PetscFunctionReturn(PETSC_SUCCESS); 11093 } 11094 11095 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"); 11096 11097 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11098 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11099 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11100 PetscFunctionReturn(PETSC_SUCCESS); 11101 } 11102 11103 /*@ 11104 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11105 11106 Collective 11107 11108 Input Parameters: 11109 + A - the matrix to create subdomains from 11110 - N - requested number of subdomains 11111 11112 Output Parameters: 11113 + n - number of subdomains resulting on this MPI process 11114 - iss - `IS` list with indices of subdomains on this MPI process 11115 11116 Level: advanced 11117 11118 Note: 11119 The number of subdomains must be smaller than the communicator size 11120 11121 .seealso: [](ch_matrices), `Mat`, `IS` 11122 @*/ 11123 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11124 { 11125 MPI_Comm comm, subcomm; 11126 PetscMPIInt size, rank, color; 11127 PetscInt rstart, rend, k; 11128 11129 PetscFunctionBegin; 11130 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11131 PetscCallMPI(MPI_Comm_size(comm, &size)); 11132 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11133 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); 11134 *n = 1; 11135 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11136 color = rank / k; 11137 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11138 PetscCall(PetscMalloc1(1, iss)); 11139 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11140 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11141 PetscCallMPI(MPI_Comm_free(&subcomm)); 11142 PetscFunctionReturn(PETSC_SUCCESS); 11143 } 11144 11145 /*@ 11146 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11147 11148 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11149 If they are not the same, uses `MatMatMatMult()`. 11150 11151 Once the coarse grid problem is constructed, correct for interpolation operators 11152 that are not of full rank, which can legitimately happen in the case of non-nested 11153 geometric multigrid. 11154 11155 Input Parameters: 11156 + restrct - restriction operator 11157 . dA - fine grid matrix 11158 . interpolate - interpolation operator 11159 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11160 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11161 11162 Output Parameter: 11163 . A - the Galerkin coarse matrix 11164 11165 Options Database Key: 11166 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11167 11168 Level: developer 11169 11170 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11171 @*/ 11172 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11173 { 11174 IS zerorows; 11175 Vec diag; 11176 11177 PetscFunctionBegin; 11178 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11179 /* Construct the coarse grid matrix */ 11180 if (interpolate == restrct) { 11181 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11182 } else { 11183 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11184 } 11185 11186 /* If the interpolation matrix is not of full rank, A will have zero rows. 11187 This can legitimately happen in the case of non-nested geometric multigrid. 11188 In that event, we set the rows of the matrix to the rows of the identity, 11189 ignoring the equations (as the RHS will also be zero). */ 11190 11191 PetscCall(MatFindZeroRows(*A, &zerorows)); 11192 11193 if (zerorows != NULL) { /* if there are any zero rows */ 11194 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11195 PetscCall(MatGetDiagonal(*A, diag)); 11196 PetscCall(VecISSet(diag, zerorows, 1.0)); 11197 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11198 PetscCall(VecDestroy(&diag)); 11199 PetscCall(ISDestroy(&zerorows)); 11200 } 11201 PetscFunctionReturn(PETSC_SUCCESS); 11202 } 11203 11204 /*@C 11205 MatSetOperation - Allows user to set a matrix operation for any matrix type 11206 11207 Logically Collective 11208 11209 Input Parameters: 11210 + mat - the matrix 11211 . op - the name of the operation 11212 - f - the function that provides the operation 11213 11214 Level: developer 11215 11216 Example Usage: 11217 .vb 11218 extern PetscErrorCode usermult(Mat, Vec, Vec); 11219 11220 PetscCall(MatCreateXXX(comm, ..., &A)); 11221 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11222 .ve 11223 11224 Notes: 11225 See the file `include/petscmat.h` for a complete list of matrix 11226 operations, which all have the form MATOP_<OPERATION>, where 11227 <OPERATION> is the name (in all capital letters) of the 11228 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11229 11230 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11231 sequence as the usual matrix interface routines, since they 11232 are intended to be accessed via the usual matrix interface 11233 routines, e.g., 11234 .vb 11235 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11236 .ve 11237 11238 In particular each function MUST return `PETSC_SUCCESS` on success and 11239 nonzero on failure. 11240 11241 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11242 11243 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11244 @*/ 11245 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11246 { 11247 PetscFunctionBegin; 11248 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11249 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11250 (((void (**)(void))mat->ops)[op]) = f; 11251 PetscFunctionReturn(PETSC_SUCCESS); 11252 } 11253 11254 /*@C 11255 MatGetOperation - Gets a matrix operation for any matrix type. 11256 11257 Not Collective 11258 11259 Input Parameters: 11260 + mat - the matrix 11261 - op - the name of the operation 11262 11263 Output Parameter: 11264 . f - the function that provides the operation 11265 11266 Level: developer 11267 11268 Example Usage: 11269 .vb 11270 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11271 11272 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11273 .ve 11274 11275 Notes: 11276 See the file include/petscmat.h for a complete list of matrix 11277 operations, which all have the form MATOP_<OPERATION>, where 11278 <OPERATION> is the name (in all capital letters) of the 11279 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11280 11281 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11282 11283 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11284 @*/ 11285 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11286 { 11287 PetscFunctionBegin; 11288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11289 *f = (((void (**)(void))mat->ops)[op]); 11290 PetscFunctionReturn(PETSC_SUCCESS); 11291 } 11292 11293 /*@ 11294 MatHasOperation - Determines whether the given matrix supports the particular operation. 11295 11296 Not Collective 11297 11298 Input Parameters: 11299 + mat - the matrix 11300 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11301 11302 Output Parameter: 11303 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11304 11305 Level: advanced 11306 11307 Note: 11308 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11309 11310 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11311 @*/ 11312 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11313 { 11314 PetscFunctionBegin; 11315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11316 PetscAssertPointer(has, 3); 11317 if (mat->ops->hasoperation) { 11318 PetscUseTypeMethod(mat, hasoperation, op, has); 11319 } else { 11320 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11321 else { 11322 *has = PETSC_FALSE; 11323 if (op == MATOP_CREATE_SUBMATRIX) { 11324 PetscMPIInt size; 11325 11326 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11327 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11328 } 11329 } 11330 } 11331 PetscFunctionReturn(PETSC_SUCCESS); 11332 } 11333 11334 /*@ 11335 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11336 11337 Collective 11338 11339 Input Parameter: 11340 . mat - the matrix 11341 11342 Output Parameter: 11343 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11344 11345 Level: beginner 11346 11347 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11348 @*/ 11349 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11350 { 11351 PetscFunctionBegin; 11352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11353 PetscValidType(mat, 1); 11354 PetscAssertPointer(cong, 2); 11355 if (!mat->rmap || !mat->cmap) { 11356 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11357 PetscFunctionReturn(PETSC_SUCCESS); 11358 } 11359 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11360 PetscCall(PetscLayoutSetUp(mat->rmap)); 11361 PetscCall(PetscLayoutSetUp(mat->cmap)); 11362 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11363 if (*cong) mat->congruentlayouts = 1; 11364 else mat->congruentlayouts = 0; 11365 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11366 PetscFunctionReturn(PETSC_SUCCESS); 11367 } 11368 11369 PetscErrorCode MatSetInf(Mat A) 11370 { 11371 PetscFunctionBegin; 11372 PetscUseTypeMethod(A, setinf); 11373 PetscFunctionReturn(PETSC_SUCCESS); 11374 } 11375 11376 /*@ 11377 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 11378 and possibly removes small values from the graph structure. 11379 11380 Collective 11381 11382 Input Parameters: 11383 + A - the matrix 11384 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11385 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11386 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11387 . num_idx - size of 'index' array 11388 - index - array of block indices to use for graph strength of connection weight 11389 11390 Output Parameter: 11391 . graph - the resulting graph 11392 11393 Level: advanced 11394 11395 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11396 @*/ 11397 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11398 { 11399 PetscFunctionBegin; 11400 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11401 PetscValidType(A, 1); 11402 PetscValidLogicalCollectiveBool(A, scale, 3); 11403 PetscAssertPointer(graph, 7); 11404 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11405 PetscFunctionReturn(PETSC_SUCCESS); 11406 } 11407 11408 /*@ 11409 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11410 meaning the same memory is used for the matrix, and no new memory is allocated. 11411 11412 Collective 11413 11414 Input Parameters: 11415 + A - the matrix 11416 - 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 11417 11418 Level: intermediate 11419 11420 Developer Note: 11421 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11422 of the arrays in the data structure are unneeded. 11423 11424 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11425 @*/ 11426 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11427 { 11428 PetscFunctionBegin; 11429 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11430 PetscUseTypeMethod(A, eliminatezeros, keep); 11431 PetscFunctionReturn(PETSC_SUCCESS); 11432 } 11433