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