1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n, st; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 207 PetscCall(MatGetSize(mat, &N, NULL)); 208 PetscCall(MatGetLocalSize(mat, &n, NULL)); 209 PetscCall(VecSet(l, 0.0)); 210 PetscCall(VecSetRandom(r, NULL)); 211 PetscCall(MatMult(mat, r, l)); 212 PetscCall(VecGetArrayRead(l, &al)); 213 } else { /* nonzero columns */ 214 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 215 PetscCall(MatGetSize(mat, NULL, &N)); 216 PetscCall(MatGetLocalSize(mat, NULL, &n)); 217 PetscCall(VecSet(r, 0.0)); 218 PetscCall(VecSetRandom(l, NULL)); 219 PetscCall(MatMultTranspose(mat, l, r)); 220 PetscCall(VecGetArrayRead(r, &al)); 221 } 222 if (tol <= 0.0) { 223 for (i = 0, nz = 0; i < n; i++) 224 if (al[i] != 0.0) nz++; 225 } else { 226 for (i = 0, nz = 0; i < n; i++) 227 if (PetscAbsScalar(al[i]) > tol) nz++; 228 } 229 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 230 if (gnz != N) { 231 PetscInt *nzr; 232 PetscCall(PetscMalloc1(nz, &nzr)); 233 if (nz) { 234 if (tol < 0) { 235 for (i = 0, nz = 0; i < n; i++) 236 if (al[i] != 0.0) nzr[nz++] = i + st; 237 } else { 238 for (i = 0, nz = 0; i < n; i++) 239 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 240 } 241 } 242 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 243 } else *nonzero = NULL; 244 if (!cols) { /* nonzero rows */ 245 PetscCall(VecRestoreArrayRead(l, &al)); 246 } else { 247 PetscCall(VecRestoreArrayRead(r, &al)); 248 } 249 PetscCall(VecDestroy(&l)); 250 PetscCall(VecDestroy(&r)); 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 /*@ 255 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 256 257 Input Parameter: 258 . mat - the matrix 259 260 Output Parameter: 261 . keptrows - the rows that are not completely zero 262 263 Level: intermediate 264 265 Note: 266 `keptrows` is set to `NULL` if all rows are nonzero. 267 268 Developer Note: 269 If `keptrows` is not `NULL`, it must be sorted. 270 271 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 272 @*/ 273 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 274 { 275 PetscFunctionBegin; 276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 277 PetscValidType(mat, 1); 278 PetscAssertPointer(keptrows, 2); 279 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 280 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 281 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 282 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 283 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindZeroRows - Locate all rows that are completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . zerorows - the rows that are completely zero 295 296 Level: intermediate 297 298 Note: 299 `zerorows` is set to `NULL` if no rows are zero. 300 301 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 302 @*/ 303 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 304 { 305 IS keptrows; 306 PetscInt m, n; 307 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(zerorows, 2); 312 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 313 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 314 In keeping with this convention, we set zerorows to NULL if there are no zero 315 rows. */ 316 if (keptrows == NULL) { 317 *zerorows = NULL; 318 } else { 319 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 320 PetscCall(ISComplement(keptrows, m, n, zerorows)); 321 PetscCall(ISDestroy(&keptrows)); 322 } 323 PetscFunctionReturn(PETSC_SUCCESS); 324 } 325 326 /*@ 327 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 328 329 Not Collective 330 331 Input Parameter: 332 . A - the matrix 333 334 Output Parameter: 335 . a - the diagonal part (which is a SEQUENTIAL matrix) 336 337 Level: advanced 338 339 Notes: 340 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 341 342 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 343 344 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 345 @*/ 346 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 347 { 348 PetscFunctionBegin; 349 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 350 PetscValidType(A, 1); 351 PetscAssertPointer(a, 2); 352 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 353 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 354 else { 355 PetscMPIInt size; 356 357 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 358 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 359 *a = A; 360 } 361 PetscFunctionReturn(PETSC_SUCCESS); 362 } 363 364 /*@ 365 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 366 367 Collective 368 369 Input Parameter: 370 . mat - the matrix 371 372 Output Parameter: 373 . trace - the sum of the diagonal entries 374 375 Level: advanced 376 377 .seealso: [](ch_matrices), `Mat` 378 @*/ 379 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 380 { 381 Vec diag; 382 383 PetscFunctionBegin; 384 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 385 PetscAssertPointer(trace, 2); 386 PetscCall(MatCreateVecs(mat, &diag, NULL)); 387 PetscCall(MatGetDiagonal(mat, diag)); 388 PetscCall(VecSum(diag, trace)); 389 PetscCall(VecDestroy(&diag)); 390 PetscFunctionReturn(PETSC_SUCCESS); 391 } 392 393 /*@ 394 MatRealPart - Zeros out the imaginary part of the matrix 395 396 Logically Collective 397 398 Input Parameter: 399 . mat - the matrix 400 401 Level: advanced 402 403 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 404 @*/ 405 PetscErrorCode MatRealPart(Mat mat) 406 { 407 PetscFunctionBegin; 408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 409 PetscValidType(mat, 1); 410 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 411 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 412 MatCheckPreallocated(mat, 1); 413 PetscUseTypeMethod(mat, realpart); 414 PetscFunctionReturn(PETSC_SUCCESS); 415 } 416 417 /*@C 418 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 419 420 Collective 421 422 Input Parameter: 423 . mat - the matrix 424 425 Output Parameters: 426 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 427 - ghosts - the global indices of the ghost points 428 429 Level: advanced 430 431 Note: 432 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 433 434 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 435 @*/ 436 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 437 { 438 PetscFunctionBegin; 439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 440 PetscValidType(mat, 1); 441 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 442 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 443 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 444 else { 445 if (nghosts) *nghosts = 0; 446 if (ghosts) *ghosts = NULL; 447 } 448 PetscFunctionReturn(PETSC_SUCCESS); 449 } 450 451 /*@ 452 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 453 454 Logically Collective 455 456 Input Parameter: 457 . mat - the matrix 458 459 Level: advanced 460 461 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 462 @*/ 463 PetscErrorCode MatImaginaryPart(Mat mat) 464 { 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 467 PetscValidType(mat, 1); 468 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 469 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 470 MatCheckPreallocated(mat, 1); 471 PetscUseTypeMethod(mat, imaginarypart); 472 PetscFunctionReturn(PETSC_SUCCESS); 473 } 474 475 /*@ 476 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 477 478 Not Collective 479 480 Input Parameter: 481 . mat - the matrix 482 483 Output Parameters: 484 + missing - is any diagonal entry missing 485 - dd - first diagonal entry that is missing (optional) on this process 486 487 Level: advanced 488 489 Note: 490 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 491 492 .seealso: [](ch_matrices), `Mat` 493 @*/ 494 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 495 { 496 PetscFunctionBegin; 497 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 498 PetscValidType(mat, 1); 499 PetscAssertPointer(missing, 2); 500 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 501 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 502 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 503 PetscFunctionReturn(PETSC_SUCCESS); 504 } 505 506 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 507 /*@C 508 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 509 for each row that you get to ensure that your application does 510 not bleed memory. 511 512 Not Collective 513 514 Input Parameters: 515 + mat - the matrix 516 - row - the row to get 517 518 Output Parameters: 519 + ncols - if not `NULL`, the number of nonzeros in `row` 520 . cols - if not `NULL`, the column numbers 521 - vals - if not `NULL`, the numerical values 522 523 Level: advanced 524 525 Notes: 526 This routine is provided for people who need to have direct access 527 to the structure of a matrix. We hope that we provide enough 528 high-level matrix routines that few users will need it. 529 530 `MatGetRow()` always returns 0-based column indices, regardless of 531 whether the internal representation is 0-based (default) or 1-based. 532 533 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 534 not wish to extract these quantities. 535 536 The user can only examine the values extracted with `MatGetRow()`; 537 the values CANNOT be altered. To change the matrix entries, one 538 must use `MatSetValues()`. 539 540 You can only have one call to `MatGetRow()` outstanding for a particular 541 matrix at a time, per processor. `MatGetRow()` can only obtain rows 542 associated with the given processor, it cannot get rows from the 543 other processors; for that we suggest using `MatCreateSubMatrices()`, then 544 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 545 is in the global number of rows. 546 547 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 548 549 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 550 551 Fortran Note: 552 The calling sequence is 553 .vb 554 MatGetRow(matrix,row,ncols,cols,values,ierr) 555 Mat matrix (input) 556 PetscInt row (input) 557 PetscInt ncols (output) 558 PetscInt cols(maxcols) (output) 559 PetscScalar values(maxcols) output 560 .ve 561 where maxcols >= maximum nonzeros in any row of the matrix. 562 563 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 564 @*/ 565 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 566 { 567 PetscInt incols; 568 569 PetscFunctionBegin; 570 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 571 PetscValidType(mat, 1); 572 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 573 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 574 MatCheckPreallocated(mat, 1); 575 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 576 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 577 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 578 if (ncols) *ncols = incols; 579 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 580 PetscFunctionReturn(PETSC_SUCCESS); 581 } 582 583 /*@ 584 MatConjugate - replaces the matrix values with their complex conjugates 585 586 Logically Collective 587 588 Input Parameter: 589 . mat - the matrix 590 591 Level: advanced 592 593 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 594 @*/ 595 PetscErrorCode MatConjugate(Mat mat) 596 { 597 PetscFunctionBegin; 598 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 599 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 601 PetscUseTypeMethod(mat, conjugate); 602 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 603 } 604 PetscFunctionReturn(PETSC_SUCCESS); 605 } 606 607 /*@C 608 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 609 610 Not Collective 611 612 Input Parameters: 613 + mat - the matrix 614 . row - the row to get 615 . ncols - the number of nonzeros 616 . cols - the columns of the nonzeros 617 - vals - if nonzero the column values 618 619 Level: advanced 620 621 Notes: 622 This routine should be called after you have finished examining the entries. 623 624 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 625 us of the array after it has been restored. If you pass `NULL`, it will 626 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 627 628 Fortran Note: 629 `MatRestoreRow()` MUST be called after `MatGetRow()` 630 before another call to `MatGetRow()` can be made. 631 632 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 633 @*/ 634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 638 if (ncols) PetscAssertPointer(ncols, 3); 639 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 640 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 641 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 642 if (ncols) *ncols = 0; 643 if (cols) *cols = NULL; 644 if (vals) *vals = NULL; 645 PetscFunctionReturn(PETSC_SUCCESS); 646 } 647 648 /*@ 649 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 650 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 651 652 Not Collective 653 654 Input Parameter: 655 . mat - the matrix 656 657 Level: advanced 658 659 Note: 660 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 661 662 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 663 @*/ 664 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 668 PetscValidType(mat, 1); 669 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 670 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 671 MatCheckPreallocated(mat, 1); 672 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 673 PetscUseTypeMethod(mat, getrowuppertriangular); 674 PetscFunctionReturn(PETSC_SUCCESS); 675 } 676 677 /*@ 678 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 701 PetscUseTypeMethod(mat, restorerowuppertriangular); 702 PetscFunctionReturn(PETSC_SUCCESS); 703 } 704 705 /*@ 706 MatSetOptionsPrefix - Sets the prefix used for searching for all 707 `Mat` options in the database. 708 709 Logically Collective 710 711 Input Parameters: 712 + A - the matrix 713 - prefix - the prefix to prepend to all option names 714 715 Level: advanced 716 717 Notes: 718 A hyphen (-) must NOT be given at the beginning of the prefix name. 719 The first character of all runtime options is AUTOMATICALLY the hyphen. 720 721 This is NOT used for options for the factorization of the matrix. Normally the 722 prefix is automatically passed in from the PC calling the factorization. To set 723 it directly use `MatSetOptionsPrefixFactor()` 724 725 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 726 @*/ 727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 728 { 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 731 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@ 736 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 737 for matrices created with `MatGetFactor()` 738 739 Logically Collective 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names for the factored matrix 744 745 Level: developer 746 747 Notes: 748 A hyphen (-) must NOT be given at the beginning of the prefix name. 749 The first character of all runtime options is AUTOMATICALLY the hyphen. 750 751 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 752 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 753 754 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 755 @*/ 756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 757 { 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 760 if (prefix) { 761 PetscAssertPointer(prefix, 2); 762 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 763 if (prefix != A->factorprefix) { 764 PetscCall(PetscFree(A->factorprefix)); 765 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 766 } 767 } else PetscCall(PetscFree(A->factorprefix)); 768 PetscFunctionReturn(PETSC_SUCCESS); 769 } 770 771 /*@ 772 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 773 for matrices created with `MatGetFactor()` 774 775 Logically Collective 776 777 Input Parameters: 778 + A - the matrix 779 - prefix - the prefix to prepend to all option names for the factored matrix 780 781 Level: developer 782 783 Notes: 784 A hyphen (-) must NOT be given at the beginning of the prefix name. 785 The first character of all runtime options is AUTOMATICALLY the hyphen. 786 787 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 788 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 789 790 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 791 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 792 `MatSetOptionsPrefix()` 793 @*/ 794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 795 { 796 size_t len1, len2, new_len; 797 798 PetscFunctionBegin; 799 PetscValidHeader(A, 1); 800 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 801 if (!A->factorprefix) { 802 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 803 PetscFunctionReturn(PETSC_SUCCESS); 804 } 805 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 806 807 PetscCall(PetscStrlen(A->factorprefix, &len1)); 808 PetscCall(PetscStrlen(prefix, &len2)); 809 new_len = len1 + len2 + 1; 810 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 811 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 812 PetscFunctionReturn(PETSC_SUCCESS); 813 } 814 815 /*@ 816 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 817 matrix options in the database. 818 819 Logically Collective 820 821 Input Parameters: 822 + A - the matrix 823 - prefix - the prefix to prepend to all option names 824 825 Level: advanced 826 827 Note: 828 A hyphen (-) must NOT be given at the beginning of the prefix name. 829 The first character of all runtime options is AUTOMATICALLY the hyphen. 830 831 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 832 @*/ 833 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 834 { 835 PetscFunctionBegin; 836 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 837 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@ 842 MatGetOptionsPrefix - Gets the prefix used for searching for all 843 matrix options in the database. 844 845 Not Collective 846 847 Input Parameter: 848 . A - the matrix 849 850 Output Parameter: 851 . prefix - pointer to the prefix string used 852 853 Level: advanced 854 855 Fortran Note: 856 The user should pass in a string `prefix` of 857 sufficient length to hold the prefix. 858 859 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 860 @*/ 861 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 862 { 863 PetscFunctionBegin; 864 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 865 PetscAssertPointer(prefix, 2); 866 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 867 PetscFunctionReturn(PETSC_SUCCESS); 868 } 869 870 /*@ 871 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 872 873 Not Collective 874 875 Input Parameter: 876 . A - the matrix 877 878 Output Parameter: 879 . state - the object state 880 881 Level: advanced 882 883 Note: 884 Object state is an integer which gets increased every time 885 the object is changed. By saving and later querying the object state 886 one can determine whether information about the object is still current. 887 888 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 889 890 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 891 @*/ 892 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 893 { 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 896 PetscAssertPointer(state, 2); 897 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 898 PetscFunctionReturn(PETSC_SUCCESS); 899 } 900 901 /*@ 902 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 903 904 Collective 905 906 Input Parameter: 907 . A - the matrix 908 909 Level: beginner 910 911 Notes: 912 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 913 914 Users can reset the preallocation to access the original memory. 915 916 Currently only supported for `MATAIJ` matrices. 917 918 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 919 @*/ 920 PetscErrorCode MatResetPreallocation(Mat A) 921 { 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 924 PetscValidType(A, 1); 925 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 926 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 927 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 928 PetscFunctionReturn(PETSC_SUCCESS); 929 } 930 931 /*@ 932 MatSetUp - Sets up the internal matrix data structures for later use. 933 934 Collective 935 936 Input Parameter: 937 . A - the matrix 938 939 Level: intermediate 940 941 Notes: 942 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 943 setting values in the matrix. 944 945 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 946 947 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 948 @*/ 949 PetscErrorCode MatSetUp(Mat A) 950 { 951 PetscFunctionBegin; 952 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 953 if (!((PetscObject)A)->type_name) { 954 PetscMPIInt size; 955 956 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 957 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 958 } 959 if (!A->preallocated) PetscTryTypeMethod(A, setup); 960 PetscCall(PetscLayoutSetUp(A->rmap)); 961 PetscCall(PetscLayoutSetUp(A->cmap)); 962 A->preallocated = PETSC_TRUE; 963 PetscFunctionReturn(PETSC_SUCCESS); 964 } 965 966 #if defined(PETSC_HAVE_SAWS) 967 #include <petscviewersaws.h> 968 #endif 969 970 /* 971 If threadsafety is on extraneous matrices may be printed 972 973 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 974 */ 975 #if !defined(PETSC_HAVE_THREADSAFETY) 976 static PetscInt insidematview = 0; 977 #endif 978 979 /*@ 980 MatViewFromOptions - View properties of the matrix based on options set in the options database 981 982 Collective 983 984 Input Parameters: 985 + A - the matrix 986 . obj - optional additional object that provides the options prefix to use 987 - name - command line option 988 989 Options Database Key: 990 . -mat_view [viewertype]:... - the viewer and its options 991 992 Level: intermediate 993 994 Note: 995 .vb 996 If no value is provided ascii:stdout is used 997 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 998 for example ascii::ascii_info prints just the information about the object not all details 999 unless :append is given filename opens in write mode, overwriting what was already there 1000 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1001 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1002 socket[:port] defaults to the standard output port 1003 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1004 .ve 1005 1006 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1007 @*/ 1008 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1009 { 1010 PetscFunctionBegin; 1011 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1012 #if !defined(PETSC_HAVE_THREADSAFETY) 1013 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1014 #endif 1015 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1016 PetscFunctionReturn(PETSC_SUCCESS); 1017 } 1018 1019 /*@ 1020 MatView - display information about a matrix in a variety ways 1021 1022 Collective on viewer 1023 1024 Input Parameters: 1025 + mat - the matrix 1026 - viewer - visualization context 1027 1028 Options Database Keys: 1029 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1030 . -mat_view ::ascii_info_detail - Prints more detailed info 1031 . -mat_view - Prints matrix in ASCII format 1032 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1033 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1034 . -display <name> - Sets display name (default is host) 1035 . -draw_pause <sec> - Sets number of seconds to pause after display 1036 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1037 . -viewer_socket_machine <machine> - - 1038 . -viewer_socket_port <port> - - 1039 . -mat_view binary - save matrix to file in binary format 1040 - -viewer_binary_filename <name> - - 1041 1042 Level: beginner 1043 1044 Notes: 1045 The available visualization contexts include 1046 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1047 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1048 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1049 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1050 1051 The user can open alternative visualization contexts with 1052 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1053 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1054 specified file; corresponding input uses `MatLoad()` 1055 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1056 an X window display 1057 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1058 Currently only the `MATSEQDENSE` and `MATAIJ` 1059 matrix types support the Socket viewer. 1060 1061 The user can call `PetscViewerPushFormat()` to specify the output 1062 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1063 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1064 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1065 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1066 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1067 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1068 format common among all matrix types 1069 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1070 format (which is in many cases the same as the default) 1071 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1072 size and structure (not the matrix entries) 1073 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1074 the matrix structure 1075 1076 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1077 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1078 1079 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1080 1081 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1082 viewer is used. 1083 1084 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1085 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1086 1087 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1088 and then use the following mouse functions. 1089 .vb 1090 left mouse: zoom in 1091 middle mouse: zoom out 1092 right mouse: continue with the simulation 1093 .ve 1094 1095 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1096 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1097 @*/ 1098 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1099 { 1100 PetscInt rows, cols, rbs, cbs; 1101 PetscBool isascii, isstring, issaws; 1102 PetscViewerFormat format; 1103 PetscMPIInt size; 1104 1105 PetscFunctionBegin; 1106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1107 PetscValidType(mat, 1); 1108 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1109 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1110 1111 PetscCall(PetscViewerGetFormat(viewer, &format)); 1112 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1113 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1114 1115 #if !defined(PETSC_HAVE_THREADSAFETY) 1116 insidematview++; 1117 #endif 1118 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1119 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1120 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1121 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1122 1123 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1124 if (isascii) { 1125 if (!mat->preallocated) { 1126 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1127 #if !defined(PETSC_HAVE_THREADSAFETY) 1128 insidematview--; 1129 #endif 1130 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1131 PetscFunctionReturn(PETSC_SUCCESS); 1132 } 1133 if (!mat->assembled) { 1134 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1135 #if !defined(PETSC_HAVE_THREADSAFETY) 1136 insidematview--; 1137 #endif 1138 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1139 PetscFunctionReturn(PETSC_SUCCESS); 1140 } 1141 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1142 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1143 MatNullSpace nullsp, transnullsp; 1144 1145 PetscCall(PetscViewerASCIIPushTab(viewer)); 1146 PetscCall(MatGetSize(mat, &rows, &cols)); 1147 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1148 if (rbs != 1 || cbs != 1) { 1149 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : "")); 1150 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1151 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1152 if (mat->factortype) { 1153 MatSolverType solver; 1154 PetscCall(MatFactorGetSolverType(mat, &solver)); 1155 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1156 } 1157 if (mat->ops->getinfo) { 1158 MatInfo info; 1159 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1160 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1161 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1162 } 1163 PetscCall(MatGetNullSpace(mat, &nullsp)); 1164 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1165 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1166 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1167 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1168 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1169 PetscCall(PetscViewerASCIIPushTab(viewer)); 1170 PetscCall(MatProductView(mat, viewer)); 1171 PetscCall(PetscViewerASCIIPopTab(viewer)); 1172 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1173 IS tmp; 1174 1175 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1176 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1177 PetscCall(PetscViewerASCIIPushTab(viewer)); 1178 PetscCall(ISView(tmp, viewer)); 1179 PetscCall(PetscViewerASCIIPopTab(viewer)); 1180 PetscCall(ISDestroy(&tmp)); 1181 } 1182 } 1183 } else if (issaws) { 1184 #if defined(PETSC_HAVE_SAWS) 1185 PetscMPIInt rank; 1186 1187 PetscCall(PetscObjectName((PetscObject)mat)); 1188 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1189 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1190 #endif 1191 } else if (isstring) { 1192 const char *type; 1193 PetscCall(MatGetType(mat, &type)); 1194 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1195 PetscTryTypeMethod(mat, view, viewer); 1196 } 1197 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1198 PetscCall(PetscViewerASCIIPushTab(viewer)); 1199 PetscUseTypeMethod(mat, viewnative, viewer); 1200 PetscCall(PetscViewerASCIIPopTab(viewer)); 1201 } else if (mat->ops->view) { 1202 PetscCall(PetscViewerASCIIPushTab(viewer)); 1203 PetscUseTypeMethod(mat, view, viewer); 1204 PetscCall(PetscViewerASCIIPopTab(viewer)); 1205 } 1206 if (isascii) { 1207 PetscCall(PetscViewerGetFormat(viewer, &format)); 1208 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1209 } 1210 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1211 #if !defined(PETSC_HAVE_THREADSAFETY) 1212 insidematview--; 1213 #endif 1214 PetscFunctionReturn(PETSC_SUCCESS); 1215 } 1216 1217 #if defined(PETSC_USE_DEBUG) 1218 #include <../src/sys/totalview/tv_data_display.h> 1219 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1220 { 1221 TV_add_row("Local rows", "int", &mat->rmap->n); 1222 TV_add_row("Local columns", "int", &mat->cmap->n); 1223 TV_add_row("Global rows", "int", &mat->rmap->N); 1224 TV_add_row("Global columns", "int", &mat->cmap->N); 1225 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1226 return TV_format_OK; 1227 } 1228 #endif 1229 1230 /*@ 1231 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1232 with `MatView()`. The matrix format is determined from the options database. 1233 Generates a parallel MPI matrix if the communicator has more than one 1234 processor. The default matrix type is `MATAIJ`. 1235 1236 Collective 1237 1238 Input Parameters: 1239 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1240 or some related function before a call to `MatLoad()` 1241 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1242 1243 Options Database Key: 1244 . -matload_block_size <bs> - set block size 1245 1246 Level: beginner 1247 1248 Notes: 1249 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1250 `Mat` before calling this routine if you wish to set it from the options database. 1251 1252 `MatLoad()` automatically loads into the options database any options 1253 given in the file filename.info where filename is the name of the file 1254 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1255 file will be ignored if you use the -viewer_binary_skip_info option. 1256 1257 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1258 sets the default matrix type AIJ and sets the local and global sizes. 1259 If type and/or size is already set, then the same are used. 1260 1261 In parallel, each processor can load a subset of rows (or the 1262 entire matrix). This routine is especially useful when a large 1263 matrix is stored on disk and only part of it is desired on each 1264 processor. For example, a parallel solver may access only some of 1265 the rows from each processor. The algorithm used here reads 1266 relatively small blocks of data rather than reading the entire 1267 matrix and then subsetting it. 1268 1269 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1270 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1271 or the sequence like 1272 .vb 1273 `PetscViewer` v; 1274 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1275 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1276 `PetscViewerSetFromOptions`(v); 1277 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1278 `PetscViewerFileSetName`(v,"datafile"); 1279 .ve 1280 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1281 $ -viewer_type {binary, hdf5} 1282 1283 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1284 and src/mat/tutorials/ex10.c with the second approach. 1285 1286 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1287 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1288 Multiple objects, both matrices and vectors, can be stored within the same file. 1289 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1290 1291 Most users should not need to know the details of the binary storage 1292 format, since `MatLoad()` and `MatView()` completely hide these details. 1293 But for anyone who is interested, the standard binary matrix storage 1294 format is 1295 1296 .vb 1297 PetscInt MAT_FILE_CLASSID 1298 PetscInt number of rows 1299 PetscInt number of columns 1300 PetscInt total number of nonzeros 1301 PetscInt *number nonzeros in each row 1302 PetscInt *column indices of all nonzeros (starting index is zero) 1303 PetscScalar *values of all nonzeros 1304 .ve 1305 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1306 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1307 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1308 1309 PETSc automatically does the byte swapping for 1310 machines that store the bytes reversed. Thus if you write your own binary 1311 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1312 and `PetscBinaryWrite()` to see how this may be done. 1313 1314 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1315 Each processor's chunk is loaded independently by its owning MPI process. 1316 Multiple objects, both matrices and vectors, can be stored within the same file. 1317 They are looked up by their PetscObject name. 1318 1319 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1320 by default the same structure and naming of the AIJ arrays and column count 1321 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1322 $ save example.mat A b -v7.3 1323 can be directly read by this routine (see Reference 1 for details). 1324 1325 Depending on your MATLAB version, this format might be a default, 1326 otherwise you can set it as default in Preferences. 1327 1328 Unless -nocompression flag is used to save the file in MATLAB, 1329 PETSc must be configured with ZLIB package. 1330 1331 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1332 1333 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1334 1335 Corresponding `MatView()` is not yet implemented. 1336 1337 The loaded matrix is actually a transpose of the original one in MATLAB, 1338 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1339 With this format, matrix is automatically transposed by PETSc, 1340 unless the matrix is marked as SPD or symmetric 1341 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1342 1343 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1344 1345 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1346 @*/ 1347 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1348 { 1349 PetscBool flg; 1350 1351 PetscFunctionBegin; 1352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1353 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1354 1355 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1356 1357 flg = PETSC_FALSE; 1358 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1359 if (flg) { 1360 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1361 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1362 } 1363 flg = PETSC_FALSE; 1364 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1365 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1366 1367 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1368 PetscUseTypeMethod(mat, load, viewer); 1369 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1370 PetscFunctionReturn(PETSC_SUCCESS); 1371 } 1372 1373 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1374 { 1375 Mat_Redundant *redund = *redundant; 1376 1377 PetscFunctionBegin; 1378 if (redund) { 1379 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1380 PetscCall(ISDestroy(&redund->isrow)); 1381 PetscCall(ISDestroy(&redund->iscol)); 1382 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1383 } else { 1384 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1385 PetscCall(PetscFree(redund->sbuf_j)); 1386 PetscCall(PetscFree(redund->sbuf_a)); 1387 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1388 PetscCall(PetscFree(redund->rbuf_j[i])); 1389 PetscCall(PetscFree(redund->rbuf_a[i])); 1390 } 1391 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1392 } 1393 1394 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1395 PetscCall(PetscFree(redund)); 1396 } 1397 PetscFunctionReturn(PETSC_SUCCESS); 1398 } 1399 1400 /*@ 1401 MatDestroy - Frees space taken by a matrix. 1402 1403 Collective 1404 1405 Input Parameter: 1406 . A - the matrix 1407 1408 Level: beginner 1409 1410 Developer Note: 1411 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1412 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1413 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1414 if changes are needed here. 1415 1416 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1417 @*/ 1418 PetscErrorCode MatDestroy(Mat *A) 1419 { 1420 PetscFunctionBegin; 1421 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1422 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1423 if (--((PetscObject)*A)->refct > 0) { 1424 *A = NULL; 1425 PetscFunctionReturn(PETSC_SUCCESS); 1426 } 1427 1428 /* if memory was published with SAWs then destroy it */ 1429 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1430 PetscTryTypeMethod(*A, destroy); 1431 1432 PetscCall(PetscFree((*A)->factorprefix)); 1433 PetscCall(PetscFree((*A)->defaultvectype)); 1434 PetscCall(PetscFree((*A)->defaultrandtype)); 1435 PetscCall(PetscFree((*A)->bsizes)); 1436 PetscCall(PetscFree((*A)->solvertype)); 1437 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1438 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1439 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1440 PetscCall(MatProductClear(*A)); 1441 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1442 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1443 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1444 PetscCall(MatDestroy(&(*A)->schur)); 1445 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1446 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1447 PetscCall(PetscHeaderDestroy(A)); 1448 PetscFunctionReturn(PETSC_SUCCESS); 1449 } 1450 1451 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1452 /*@ 1453 MatSetValues - Inserts or adds a block of values into a matrix. 1454 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1455 MUST be called after all calls to `MatSetValues()` have been completed. 1456 1457 Not Collective 1458 1459 Input Parameters: 1460 + mat - the matrix 1461 . v - a logically two-dimensional array of values 1462 . m - the number of rows 1463 . idxm - the global indices of the rows 1464 . n - the number of columns 1465 . idxn - the global indices of the columns 1466 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1467 1468 Level: beginner 1469 1470 Notes: 1471 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1472 1473 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1474 options cannot be mixed without intervening calls to the assembly 1475 routines. 1476 1477 `MatSetValues()` uses 0-based row and column numbers in Fortran 1478 as well as in C. 1479 1480 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1481 simply ignored. This allows easily inserting element stiffness matrices 1482 with homogeneous Dirichlet boundary conditions that you don't want represented 1483 in the matrix. 1484 1485 Efficiency Alert: 1486 The routine `MatSetValuesBlocked()` may offer much better efficiency 1487 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1488 1489 Fortran Notes: 1490 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1491 .vb 1492 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1493 .ve 1494 1495 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1496 1497 Developer Note: 1498 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1499 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1500 1501 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1502 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1503 @*/ 1504 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1505 { 1506 PetscFunctionBeginHot; 1507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1508 PetscValidType(mat, 1); 1509 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1510 PetscAssertPointer(idxm, 3); 1511 PetscAssertPointer(idxn, 5); 1512 MatCheckPreallocated(mat, 1); 1513 1514 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1515 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1516 1517 if (PetscDefined(USE_DEBUG)) { 1518 PetscInt i, j; 1519 1520 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1521 if (v) { 1522 for (i = 0; i < m; i++) { 1523 for (j = 0; j < n; j++) { 1524 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1525 #if defined(PETSC_USE_COMPLEX) 1526 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1527 #else 1528 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1529 #endif 1530 } 1531 } 1532 } 1533 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1534 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1535 } 1536 1537 if (mat->assembled) { 1538 mat->was_assembled = PETSC_TRUE; 1539 mat->assembled = PETSC_FALSE; 1540 } 1541 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1542 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1543 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1544 PetscFunctionReturn(PETSC_SUCCESS); 1545 } 1546 1547 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1548 /*@ 1549 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1550 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1551 MUST be called after all calls to `MatSetValues()` have been completed. 1552 1553 Not Collective 1554 1555 Input Parameters: 1556 + mat - the matrix 1557 . v - a logically two-dimensional array of values 1558 . ism - the rows to provide 1559 . isn - the columns to provide 1560 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1561 1562 Level: beginner 1563 1564 Notes: 1565 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1566 1567 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1568 options cannot be mixed without intervening calls to the assembly 1569 routines. 1570 1571 `MatSetValues()` uses 0-based row and column numbers in Fortran 1572 as well as in C. 1573 1574 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1575 simply ignored. This allows easily inserting element stiffness matrices 1576 with homogeneous Dirichlet boundary conditions that you don't want represented 1577 in the matrix. 1578 1579 Efficiency Alert: 1580 The routine `MatSetValuesBlocked()` may offer much better efficiency 1581 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1582 1583 This is currently not optimized for any particular `ISType` 1584 1585 Developer Note: 1586 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1587 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1588 1589 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1590 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1591 @*/ 1592 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1593 { 1594 PetscInt m, n; 1595 const PetscInt *rows, *cols; 1596 1597 PetscFunctionBeginHot; 1598 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1599 PetscCall(ISGetIndices(ism, &rows)); 1600 PetscCall(ISGetIndices(isn, &cols)); 1601 PetscCall(ISGetLocalSize(ism, &m)); 1602 PetscCall(ISGetLocalSize(isn, &n)); 1603 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1604 PetscCall(ISRestoreIndices(ism, &rows)); 1605 PetscCall(ISRestoreIndices(isn, &cols)); 1606 PetscFunctionReturn(PETSC_SUCCESS); 1607 } 1608 1609 /*@ 1610 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1611 values into a matrix 1612 1613 Not Collective 1614 1615 Input Parameters: 1616 + mat - the matrix 1617 . row - the (block) row to set 1618 - v - a logically two-dimensional array of values 1619 1620 Level: intermediate 1621 1622 Notes: 1623 The values, `v`, are column-oriented (for the block version) and sorted 1624 1625 All the nonzero values in `row` must be provided 1626 1627 The matrix must have previously had its column indices set, likely by having been assembled. 1628 1629 `row` must belong to this MPI process 1630 1631 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1632 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1633 @*/ 1634 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1635 { 1636 PetscInt globalrow; 1637 1638 PetscFunctionBegin; 1639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1640 PetscValidType(mat, 1); 1641 PetscAssertPointer(v, 3); 1642 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1643 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1644 PetscFunctionReturn(PETSC_SUCCESS); 1645 } 1646 1647 /*@ 1648 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1649 values into a matrix 1650 1651 Not Collective 1652 1653 Input Parameters: 1654 + mat - the matrix 1655 . row - the (block) row to set 1656 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1657 1658 Level: advanced 1659 1660 Notes: 1661 The values, `v`, are column-oriented for the block version. 1662 1663 All the nonzeros in `row` must be provided 1664 1665 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1666 1667 `row` must belong to this process 1668 1669 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1670 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1671 @*/ 1672 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1673 { 1674 PetscFunctionBeginHot; 1675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1676 PetscValidType(mat, 1); 1677 MatCheckPreallocated(mat, 1); 1678 PetscAssertPointer(v, 3); 1679 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1680 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1681 mat->insertmode = INSERT_VALUES; 1682 1683 if (mat->assembled) { 1684 mat->was_assembled = PETSC_TRUE; 1685 mat->assembled = PETSC_FALSE; 1686 } 1687 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1688 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1689 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1690 PetscFunctionReturn(PETSC_SUCCESS); 1691 } 1692 1693 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1694 /*@ 1695 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1696 Using structured grid indexing 1697 1698 Not Collective 1699 1700 Input Parameters: 1701 + mat - the matrix 1702 . m - number of rows being entered 1703 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1704 . n - number of columns being entered 1705 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1706 . v - a logically two-dimensional array of values 1707 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1708 1709 Level: beginner 1710 1711 Notes: 1712 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1713 1714 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1715 options cannot be mixed without intervening calls to the assembly 1716 routines. 1717 1718 The grid coordinates are across the entire grid, not just the local portion 1719 1720 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1721 as well as in C. 1722 1723 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1724 1725 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1726 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1727 1728 The columns and rows in the stencil passed in MUST be contained within the 1729 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1730 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1731 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1732 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1733 1734 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1735 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1736 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1737 `DM_BOUNDARY_PERIODIC` boundary type. 1738 1739 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1740 a single value per point) you can skip filling those indices. 1741 1742 Inspired by the structured grid interface to the HYPRE package 1743 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1744 1745 Efficiency Alert: 1746 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1747 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1748 1749 Fortran Note: 1750 `idxm` and `idxn` should be declared as 1751 $ MatStencil idxm(4,m),idxn(4,n) 1752 and the values inserted using 1753 .vb 1754 idxm(MatStencil_i,1) = i 1755 idxm(MatStencil_j,1) = j 1756 idxm(MatStencil_k,1) = k 1757 idxm(MatStencil_c,1) = c 1758 etc 1759 .ve 1760 1761 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1762 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1763 @*/ 1764 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1765 { 1766 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1767 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1768 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1769 1770 PetscFunctionBegin; 1771 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1772 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1773 PetscValidType(mat, 1); 1774 PetscAssertPointer(idxm, 3); 1775 PetscAssertPointer(idxn, 5); 1776 1777 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1778 jdxm = buf; 1779 jdxn = buf + m; 1780 } else { 1781 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1782 jdxm = bufm; 1783 jdxn = bufn; 1784 } 1785 for (i = 0; i < m; i++) { 1786 for (j = 0; j < 3 - sdim; j++) dxm++; 1787 tmp = *dxm++ - starts[0]; 1788 for (j = 0; j < dim - 1; j++) { 1789 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1790 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1791 } 1792 if (mat->stencil.noc) dxm++; 1793 jdxm[i] = tmp; 1794 } 1795 for (i = 0; i < n; i++) { 1796 for (j = 0; j < 3 - sdim; j++) dxn++; 1797 tmp = *dxn++ - starts[0]; 1798 for (j = 0; j < dim - 1; j++) { 1799 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1800 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1801 } 1802 if (mat->stencil.noc) dxn++; 1803 jdxn[i] = tmp; 1804 } 1805 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1806 PetscCall(PetscFree2(bufm, bufn)); 1807 PetscFunctionReturn(PETSC_SUCCESS); 1808 } 1809 1810 /*@ 1811 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1812 Using structured grid indexing 1813 1814 Not Collective 1815 1816 Input Parameters: 1817 + mat - the matrix 1818 . m - number of rows being entered 1819 . idxm - grid coordinates for matrix rows being entered 1820 . n - number of columns being entered 1821 . idxn - grid coordinates for matrix columns being entered 1822 . v - a logically two-dimensional array of values 1823 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1824 1825 Level: beginner 1826 1827 Notes: 1828 By default the values, `v`, are row-oriented and unsorted. 1829 See `MatSetOption()` for other options. 1830 1831 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1832 options cannot be mixed without intervening calls to the assembly 1833 routines. 1834 1835 The grid coordinates are across the entire grid, not just the local portion 1836 1837 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1838 as well as in C. 1839 1840 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1841 1842 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1843 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1844 1845 The columns and rows in the stencil passed in MUST be contained within the 1846 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1847 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1848 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1849 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1850 1851 Negative indices may be passed in idxm and idxn, these rows and columns are 1852 simply ignored. This allows easily inserting element stiffness matrices 1853 with homogeneous Dirichlet boundary conditions that you don't want represented 1854 in the matrix. 1855 1856 Inspired by the structured grid interface to the HYPRE package 1857 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1858 1859 Fortran Note: 1860 `idxm` and `idxn` should be declared as 1861 $ MatStencil idxm(4,m),idxn(4,n) 1862 and the values inserted using 1863 .vb 1864 idxm(MatStencil_i,1) = i 1865 idxm(MatStencil_j,1) = j 1866 idxm(MatStencil_k,1) = k 1867 etc 1868 .ve 1869 1870 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1871 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1872 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1873 @*/ 1874 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1875 { 1876 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1877 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1878 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1879 1880 PetscFunctionBegin; 1881 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1883 PetscValidType(mat, 1); 1884 PetscAssertPointer(idxm, 3); 1885 PetscAssertPointer(idxn, 5); 1886 PetscAssertPointer(v, 6); 1887 1888 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1889 jdxm = buf; 1890 jdxn = buf + m; 1891 } else { 1892 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1893 jdxm = bufm; 1894 jdxn = bufn; 1895 } 1896 for (i = 0; i < m; i++) { 1897 for (j = 0; j < 3 - sdim; j++) dxm++; 1898 tmp = *dxm++ - starts[0]; 1899 for (j = 0; j < sdim - 1; j++) { 1900 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1901 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1902 } 1903 dxm++; 1904 jdxm[i] = tmp; 1905 } 1906 for (i = 0; i < n; i++) { 1907 for (j = 0; j < 3 - sdim; j++) dxn++; 1908 tmp = *dxn++ - starts[0]; 1909 for (j = 0; j < sdim - 1; j++) { 1910 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1911 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1912 } 1913 dxn++; 1914 jdxn[i] = tmp; 1915 } 1916 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1917 PetscCall(PetscFree2(bufm, bufn)); 1918 PetscFunctionReturn(PETSC_SUCCESS); 1919 } 1920 1921 /*@ 1922 MatSetStencil - Sets the grid information for setting values into a matrix via 1923 `MatSetValuesStencil()` 1924 1925 Not Collective 1926 1927 Input Parameters: 1928 + mat - the matrix 1929 . dim - dimension of the grid 1, 2, or 3 1930 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1931 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1932 - dof - number of degrees of freedom per node 1933 1934 Level: beginner 1935 1936 Notes: 1937 Inspired by the structured grid interface to the HYPRE package 1938 (www.llnl.gov/CASC/hyper) 1939 1940 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1941 user. 1942 1943 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1944 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1945 @*/ 1946 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1947 { 1948 PetscFunctionBegin; 1949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1950 PetscAssertPointer(dims, 3); 1951 PetscAssertPointer(starts, 4); 1952 1953 mat->stencil.dim = dim + (dof > 1); 1954 for (PetscInt i = 0; i < dim; i++) { 1955 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1956 mat->stencil.starts[i] = starts[dim - i - 1]; 1957 } 1958 mat->stencil.dims[dim] = dof; 1959 mat->stencil.starts[dim] = 0; 1960 mat->stencil.noc = (PetscBool)(dof == 1); 1961 PetscFunctionReturn(PETSC_SUCCESS); 1962 } 1963 1964 /*@ 1965 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1966 1967 Not Collective 1968 1969 Input Parameters: 1970 + mat - the matrix 1971 . v - a logically two-dimensional array of values 1972 . m - the number of block rows 1973 . idxm - the global block indices 1974 . n - the number of block columns 1975 . idxn - the global block indices 1976 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1977 1978 Level: intermediate 1979 1980 Notes: 1981 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1982 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1983 1984 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1985 NOT the total number of rows/columns; for example, if the block size is 2 and 1986 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1987 The values in `idxm` would be 1 2; that is the first index for each block divided by 1988 the block size. 1989 1990 You must call `MatSetBlockSize()` when constructing this matrix (before 1991 preallocating it). 1992 1993 By default the values, `v`, are row-oriented, so the layout of 1994 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1995 1996 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1997 options cannot be mixed without intervening calls to the assembly 1998 routines. 1999 2000 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2001 as well as in C. 2002 2003 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2004 simply ignored. This allows easily inserting element stiffness matrices 2005 with homogeneous Dirichlet boundary conditions that you don't want represented 2006 in the matrix. 2007 2008 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2009 internal searching must be done to determine where to place the 2010 data in the matrix storage space. By instead inserting blocks of 2011 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2012 reduced. 2013 2014 Example: 2015 .vb 2016 Suppose m=n=2 and block size(bs) = 2 The array is 2017 2018 1 2 | 3 4 2019 5 6 | 7 8 2020 - - - | - - - 2021 9 10 | 11 12 2022 13 14 | 15 16 2023 2024 v[] should be passed in like 2025 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2026 2027 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2028 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2029 .ve 2030 2031 Fortran Notes: 2032 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2033 .vb 2034 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2035 .ve 2036 2037 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2038 2039 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2040 @*/ 2041 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2042 { 2043 PetscFunctionBeginHot; 2044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2045 PetscValidType(mat, 1); 2046 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2047 PetscAssertPointer(idxm, 3); 2048 PetscAssertPointer(idxn, 5); 2049 MatCheckPreallocated(mat, 1); 2050 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2051 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2052 if (PetscDefined(USE_DEBUG)) { 2053 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2054 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2055 } 2056 if (PetscDefined(USE_DEBUG)) { 2057 PetscInt rbs, cbs, M, N, i; 2058 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2059 PetscCall(MatGetSize(mat, &M, &N)); 2060 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M); 2061 for (i = 0; i < n; i++) 2062 PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N); 2063 } 2064 if (mat->assembled) { 2065 mat->was_assembled = PETSC_TRUE; 2066 mat->assembled = PETSC_FALSE; 2067 } 2068 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2069 if (mat->ops->setvaluesblocked) { 2070 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2071 } else { 2072 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2073 PetscInt i, j, bs, cbs; 2074 2075 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2076 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2077 iidxm = buf; 2078 iidxn = buf + m * bs; 2079 } else { 2080 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2081 iidxm = bufr; 2082 iidxn = bufc; 2083 } 2084 for (i = 0; i < m; i++) { 2085 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2086 } 2087 if (m != n || bs != cbs || idxm != idxn) { 2088 for (i = 0; i < n; i++) { 2089 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2090 } 2091 } else iidxn = iidxm; 2092 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2093 PetscCall(PetscFree2(bufr, bufc)); 2094 } 2095 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2096 PetscFunctionReturn(PETSC_SUCCESS); 2097 } 2098 2099 /*@ 2100 MatGetValues - Gets a block of local values from a matrix. 2101 2102 Not Collective; can only return values that are owned by the give process 2103 2104 Input Parameters: 2105 + mat - the matrix 2106 . v - a logically two-dimensional array for storing the values 2107 . m - the number of rows 2108 . idxm - the global indices of the rows 2109 . n - the number of columns 2110 - idxn - the global indices of the columns 2111 2112 Level: advanced 2113 2114 Notes: 2115 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2116 The values, `v`, are then returned in a row-oriented format, 2117 analogous to that used by default in `MatSetValues()`. 2118 2119 `MatGetValues()` uses 0-based row and column numbers in 2120 Fortran as well as in C. 2121 2122 `MatGetValues()` requires that the matrix has been assembled 2123 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2124 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2125 without intermediate matrix assembly. 2126 2127 Negative row or column indices will be ignored and those locations in `v` will be 2128 left unchanged. 2129 2130 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2131 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2132 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2133 2134 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2135 @*/ 2136 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2137 { 2138 PetscFunctionBegin; 2139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2140 PetscValidType(mat, 1); 2141 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2142 PetscAssertPointer(idxm, 3); 2143 PetscAssertPointer(idxn, 5); 2144 PetscAssertPointer(v, 6); 2145 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2146 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2147 MatCheckPreallocated(mat, 1); 2148 2149 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2150 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2151 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2152 PetscFunctionReturn(PETSC_SUCCESS); 2153 } 2154 2155 /*@ 2156 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2157 defined previously by `MatSetLocalToGlobalMapping()` 2158 2159 Not Collective 2160 2161 Input Parameters: 2162 + mat - the matrix 2163 . nrow - number of rows 2164 . irow - the row local indices 2165 . ncol - number of columns 2166 - icol - the column local indices 2167 2168 Output Parameter: 2169 . y - a logically two-dimensional array of values 2170 2171 Level: advanced 2172 2173 Notes: 2174 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2175 2176 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2177 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2178 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2179 with `MatSetLocalToGlobalMapping()`. 2180 2181 Developer Note: 2182 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2183 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2184 2185 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2186 `MatSetValuesLocal()`, `MatGetValues()` 2187 @*/ 2188 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2189 { 2190 PetscFunctionBeginHot; 2191 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2192 PetscValidType(mat, 1); 2193 MatCheckPreallocated(mat, 1); 2194 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2195 PetscAssertPointer(irow, 3); 2196 PetscAssertPointer(icol, 5); 2197 if (PetscDefined(USE_DEBUG)) { 2198 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2199 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2200 } 2201 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2202 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2203 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2204 else { 2205 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2206 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2207 irowm = buf; 2208 icolm = buf + nrow; 2209 } else { 2210 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2211 irowm = bufr; 2212 icolm = bufc; 2213 } 2214 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2215 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2216 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2217 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2218 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2219 PetscCall(PetscFree2(bufr, bufc)); 2220 } 2221 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2222 PetscFunctionReturn(PETSC_SUCCESS); 2223 } 2224 2225 /*@ 2226 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2227 the same size. Currently, this can only be called once and creates the given matrix. 2228 2229 Not Collective 2230 2231 Input Parameters: 2232 + mat - the matrix 2233 . nb - the number of blocks 2234 . bs - the number of rows (and columns) in each block 2235 . rows - a concatenation of the rows for each block 2236 - v - a concatenation of logically two-dimensional arrays of values 2237 2238 Level: advanced 2239 2240 Notes: 2241 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2242 2243 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2244 2245 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2246 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2247 @*/ 2248 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2249 { 2250 PetscFunctionBegin; 2251 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2252 PetscValidType(mat, 1); 2253 PetscAssertPointer(rows, 4); 2254 PetscAssertPointer(v, 5); 2255 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2256 2257 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2258 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2259 else { 2260 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2261 } 2262 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2263 PetscFunctionReturn(PETSC_SUCCESS); 2264 } 2265 2266 /*@ 2267 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2268 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2269 using a local (per-processor) numbering. 2270 2271 Not Collective 2272 2273 Input Parameters: 2274 + x - the matrix 2275 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2276 - cmapping - column mapping 2277 2278 Level: intermediate 2279 2280 Note: 2281 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2282 2283 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2284 @*/ 2285 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2286 { 2287 PetscFunctionBegin; 2288 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2289 PetscValidType(x, 1); 2290 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2291 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2292 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2293 else { 2294 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2295 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2296 } 2297 PetscFunctionReturn(PETSC_SUCCESS); 2298 } 2299 2300 /*@ 2301 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2302 2303 Not Collective 2304 2305 Input Parameter: 2306 . A - the matrix 2307 2308 Output Parameters: 2309 + rmapping - row mapping 2310 - cmapping - column mapping 2311 2312 Level: advanced 2313 2314 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2315 @*/ 2316 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2317 { 2318 PetscFunctionBegin; 2319 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2320 PetscValidType(A, 1); 2321 if (rmapping) { 2322 PetscAssertPointer(rmapping, 2); 2323 *rmapping = A->rmap->mapping; 2324 } 2325 if (cmapping) { 2326 PetscAssertPointer(cmapping, 3); 2327 *cmapping = A->cmap->mapping; 2328 } 2329 PetscFunctionReturn(PETSC_SUCCESS); 2330 } 2331 2332 /*@ 2333 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2334 2335 Logically Collective 2336 2337 Input Parameters: 2338 + A - the matrix 2339 . rmap - row layout 2340 - cmap - column layout 2341 2342 Level: advanced 2343 2344 Note: 2345 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2346 2347 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2348 @*/ 2349 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2350 { 2351 PetscFunctionBegin; 2352 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2353 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2354 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2355 PetscFunctionReturn(PETSC_SUCCESS); 2356 } 2357 2358 /*@ 2359 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2360 2361 Not Collective 2362 2363 Input Parameter: 2364 . A - the matrix 2365 2366 Output Parameters: 2367 + rmap - row layout 2368 - cmap - column layout 2369 2370 Level: advanced 2371 2372 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2373 @*/ 2374 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2375 { 2376 PetscFunctionBegin; 2377 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2378 PetscValidType(A, 1); 2379 if (rmap) { 2380 PetscAssertPointer(rmap, 2); 2381 *rmap = A->rmap; 2382 } 2383 if (cmap) { 2384 PetscAssertPointer(cmap, 3); 2385 *cmap = A->cmap; 2386 } 2387 PetscFunctionReturn(PETSC_SUCCESS); 2388 } 2389 2390 /*@ 2391 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2392 using a local numbering of the rows and columns. 2393 2394 Not Collective 2395 2396 Input Parameters: 2397 + mat - the matrix 2398 . nrow - number of rows 2399 . irow - the row local indices 2400 . ncol - number of columns 2401 . icol - the column local indices 2402 . y - a logically two-dimensional array of values 2403 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2404 2405 Level: intermediate 2406 2407 Notes: 2408 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2409 2410 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2411 options cannot be mixed without intervening calls to the assembly 2412 routines. 2413 2414 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2415 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2416 2417 Fortran Notes: 2418 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2419 .vb 2420 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2421 .ve 2422 2423 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2424 2425 Developer Note: 2426 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2427 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2428 2429 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2430 `MatGetValuesLocal()` 2431 @*/ 2432 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2433 { 2434 PetscFunctionBeginHot; 2435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2436 PetscValidType(mat, 1); 2437 MatCheckPreallocated(mat, 1); 2438 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2439 PetscAssertPointer(irow, 3); 2440 PetscAssertPointer(icol, 5); 2441 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2442 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2443 if (PetscDefined(USE_DEBUG)) { 2444 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2445 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2446 } 2447 2448 if (mat->assembled) { 2449 mat->was_assembled = PETSC_TRUE; 2450 mat->assembled = PETSC_FALSE; 2451 } 2452 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2453 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2454 else { 2455 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2456 const PetscInt *irowm, *icolm; 2457 2458 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2459 bufr = buf; 2460 bufc = buf + nrow; 2461 irowm = bufr; 2462 icolm = bufc; 2463 } else { 2464 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2465 irowm = bufr; 2466 icolm = bufc; 2467 } 2468 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2469 else irowm = irow; 2470 if (mat->cmap->mapping) { 2471 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2472 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2473 } else icolm = irowm; 2474 } else icolm = icol; 2475 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2476 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2477 } 2478 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2479 PetscFunctionReturn(PETSC_SUCCESS); 2480 } 2481 2482 /*@ 2483 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2484 using a local ordering of the nodes a block at a time. 2485 2486 Not Collective 2487 2488 Input Parameters: 2489 + mat - the matrix 2490 . nrow - number of rows 2491 . irow - the row local indices 2492 . ncol - number of columns 2493 . icol - the column local indices 2494 . y - a logically two-dimensional array of values 2495 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2496 2497 Level: intermediate 2498 2499 Notes: 2500 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2501 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2502 2503 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2504 options cannot be mixed without intervening calls to the assembly 2505 routines. 2506 2507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2508 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2509 2510 Fortran Notes: 2511 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2512 .vb 2513 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2514 .ve 2515 2516 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2517 2518 Developer Note: 2519 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2520 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2521 2522 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2523 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2524 @*/ 2525 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2526 { 2527 PetscFunctionBeginHot; 2528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2529 PetscValidType(mat, 1); 2530 MatCheckPreallocated(mat, 1); 2531 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2532 PetscAssertPointer(irow, 3); 2533 PetscAssertPointer(icol, 5); 2534 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2535 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2536 if (PetscDefined(USE_DEBUG)) { 2537 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2538 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2539 } 2540 2541 if (mat->assembled) { 2542 mat->was_assembled = PETSC_TRUE; 2543 mat->assembled = PETSC_FALSE; 2544 } 2545 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2546 PetscInt irbs, rbs; 2547 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2548 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2549 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2550 } 2551 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2552 PetscInt icbs, cbs; 2553 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2554 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2555 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2556 } 2557 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2558 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2559 else { 2560 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2561 const PetscInt *irowm, *icolm; 2562 2563 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2564 bufr = buf; 2565 bufc = buf + nrow; 2566 irowm = bufr; 2567 icolm = bufc; 2568 } else { 2569 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2570 irowm = bufr; 2571 icolm = bufc; 2572 } 2573 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2574 else irowm = irow; 2575 if (mat->cmap->mapping) { 2576 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2577 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2578 } else icolm = irowm; 2579 } else icolm = icol; 2580 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2581 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2582 } 2583 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2584 PetscFunctionReturn(PETSC_SUCCESS); 2585 } 2586 2587 /*@ 2588 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2589 2590 Collective 2591 2592 Input Parameters: 2593 + mat - the matrix 2594 - x - the vector to be multiplied 2595 2596 Output Parameter: 2597 . y - the result 2598 2599 Level: developer 2600 2601 Note: 2602 The vectors `x` and `y` cannot be the same. I.e., one cannot 2603 call `MatMultDiagonalBlock`(A,y,y). 2604 2605 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2606 @*/ 2607 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2608 { 2609 PetscFunctionBegin; 2610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2611 PetscValidType(mat, 1); 2612 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2613 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2614 2615 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2616 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2617 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2618 MatCheckPreallocated(mat, 1); 2619 2620 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2621 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2622 PetscFunctionReturn(PETSC_SUCCESS); 2623 } 2624 2625 /*@ 2626 MatMult - Computes the matrix-vector product, $y = Ax$. 2627 2628 Neighbor-wise Collective 2629 2630 Input Parameters: 2631 + mat - the matrix 2632 - x - the vector to be multiplied 2633 2634 Output Parameter: 2635 . y - the result 2636 2637 Level: beginner 2638 2639 Note: 2640 The vectors `x` and `y` cannot be the same. I.e., one cannot 2641 call `MatMult`(A,y,y). 2642 2643 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2644 @*/ 2645 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2646 { 2647 PetscFunctionBegin; 2648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2649 PetscValidType(mat, 1); 2650 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2651 VecCheckAssembled(x); 2652 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2653 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2654 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2655 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2656 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2657 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2658 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2659 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2660 PetscCall(VecSetErrorIfLocked(y, 3)); 2661 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2662 MatCheckPreallocated(mat, 1); 2663 2664 PetscCall(VecLockReadPush(x)); 2665 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2666 PetscUseTypeMethod(mat, mult, x, y); 2667 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2668 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2669 PetscCall(VecLockReadPop(x)); 2670 PetscFunctionReturn(PETSC_SUCCESS); 2671 } 2672 2673 /*@ 2674 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2675 2676 Neighbor-wise Collective 2677 2678 Input Parameters: 2679 + mat - the matrix 2680 - x - the vector to be multiplied 2681 2682 Output Parameter: 2683 . y - the result 2684 2685 Level: beginner 2686 2687 Notes: 2688 The vectors `x` and `y` cannot be the same. I.e., one cannot 2689 call `MatMultTranspose`(A,y,y). 2690 2691 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2692 use `MatMultHermitianTranspose()` 2693 2694 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2695 @*/ 2696 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2697 { 2698 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2699 2700 PetscFunctionBegin; 2701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2702 PetscValidType(mat, 1); 2703 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2704 VecCheckAssembled(x); 2705 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2706 2707 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2708 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2709 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2710 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2711 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2712 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2713 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2714 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2715 MatCheckPreallocated(mat, 1); 2716 2717 if (!mat->ops->multtranspose) { 2718 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2719 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2720 } else op = mat->ops->multtranspose; 2721 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2722 PetscCall(VecLockReadPush(x)); 2723 PetscCall((*op)(mat, x, y)); 2724 PetscCall(VecLockReadPop(x)); 2725 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2726 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2727 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2728 PetscFunctionReturn(PETSC_SUCCESS); 2729 } 2730 2731 /*@ 2732 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2733 2734 Neighbor-wise Collective 2735 2736 Input Parameters: 2737 + mat - the matrix 2738 - x - the vector to be multiplied 2739 2740 Output Parameter: 2741 . y - the result 2742 2743 Level: beginner 2744 2745 Notes: 2746 The vectors `x` and `y` cannot be the same. I.e., one cannot 2747 call `MatMultHermitianTranspose`(A,y,y). 2748 2749 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2750 2751 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2752 2753 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2754 @*/ 2755 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2756 { 2757 PetscFunctionBegin; 2758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2759 PetscValidType(mat, 1); 2760 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2761 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2762 2763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2765 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2766 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2767 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2768 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2769 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2770 MatCheckPreallocated(mat, 1); 2771 2772 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2773 #if defined(PETSC_USE_COMPLEX) 2774 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2775 PetscCall(VecLockReadPush(x)); 2776 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2777 else PetscUseTypeMethod(mat, mult, x, y); 2778 PetscCall(VecLockReadPop(x)); 2779 } else { 2780 Vec w; 2781 PetscCall(VecDuplicate(x, &w)); 2782 PetscCall(VecCopy(x, w)); 2783 PetscCall(VecConjugate(w)); 2784 PetscCall(MatMultTranspose(mat, w, y)); 2785 PetscCall(VecDestroy(&w)); 2786 PetscCall(VecConjugate(y)); 2787 } 2788 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2789 #else 2790 PetscCall(MatMultTranspose(mat, x, y)); 2791 #endif 2792 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2793 PetscFunctionReturn(PETSC_SUCCESS); 2794 } 2795 2796 /*@ 2797 MatMultAdd - Computes $v3 = v2 + A * v1$. 2798 2799 Neighbor-wise Collective 2800 2801 Input Parameters: 2802 + mat - the matrix 2803 . v1 - the vector to be multiplied by `mat` 2804 - v2 - the vector to be added to the result 2805 2806 Output Parameter: 2807 . v3 - the result 2808 2809 Level: beginner 2810 2811 Note: 2812 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2813 call `MatMultAdd`(A,v1,v2,v1). 2814 2815 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2816 @*/ 2817 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2818 { 2819 PetscFunctionBegin; 2820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2821 PetscValidType(mat, 1); 2822 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2823 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2824 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2825 2826 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2827 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2828 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2829 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2830 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2831 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2832 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 MatCheckPreallocated(mat, 1); 2835 2836 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2837 PetscCall(VecLockReadPush(v1)); 2838 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2839 PetscCall(VecLockReadPop(v1)); 2840 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2841 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2842 PetscFunctionReturn(PETSC_SUCCESS); 2843 } 2844 2845 /*@ 2846 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2847 2848 Neighbor-wise Collective 2849 2850 Input Parameters: 2851 + mat - the matrix 2852 . v1 - the vector to be multiplied by the transpose of the matrix 2853 - v2 - the vector to be added to the result 2854 2855 Output Parameter: 2856 . v3 - the result 2857 2858 Level: beginner 2859 2860 Note: 2861 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2862 call `MatMultTransposeAdd`(A,v1,v2,v1). 2863 2864 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2865 @*/ 2866 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2867 { 2868 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2869 2870 PetscFunctionBegin; 2871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2872 PetscValidType(mat, 1); 2873 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2874 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2875 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2876 2877 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2878 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2879 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2880 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2881 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2882 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2883 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2884 MatCheckPreallocated(mat, 1); 2885 2886 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2887 PetscCall(VecLockReadPush(v1)); 2888 PetscCall((*op)(mat, v1, v2, v3)); 2889 PetscCall(VecLockReadPop(v1)); 2890 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2891 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2892 PetscFunctionReturn(PETSC_SUCCESS); 2893 } 2894 2895 /*@ 2896 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2897 2898 Neighbor-wise Collective 2899 2900 Input Parameters: 2901 + mat - the matrix 2902 . v1 - the vector to be multiplied by the Hermitian transpose 2903 - v2 - the vector to be added to the result 2904 2905 Output Parameter: 2906 . v3 - the result 2907 2908 Level: beginner 2909 2910 Note: 2911 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2912 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2913 2914 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2915 @*/ 2916 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2917 { 2918 PetscFunctionBegin; 2919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2920 PetscValidType(mat, 1); 2921 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2922 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2923 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2924 2925 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2926 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2927 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2928 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2929 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2930 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2931 MatCheckPreallocated(mat, 1); 2932 2933 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2934 PetscCall(VecLockReadPush(v1)); 2935 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2936 else { 2937 Vec w, z; 2938 PetscCall(VecDuplicate(v1, &w)); 2939 PetscCall(VecCopy(v1, w)); 2940 PetscCall(VecConjugate(w)); 2941 PetscCall(VecDuplicate(v3, &z)); 2942 PetscCall(MatMultTranspose(mat, w, z)); 2943 PetscCall(VecDestroy(&w)); 2944 PetscCall(VecConjugate(z)); 2945 if (v2 != v3) { 2946 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2947 } else { 2948 PetscCall(VecAXPY(v3, 1.0, z)); 2949 } 2950 PetscCall(VecDestroy(&z)); 2951 } 2952 PetscCall(VecLockReadPop(v1)); 2953 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2954 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2955 PetscFunctionReturn(PETSC_SUCCESS); 2956 } 2957 2958 /*@ 2959 MatGetFactorType - gets the type of factorization a matrix is 2960 2961 Not Collective 2962 2963 Input Parameter: 2964 . mat - the matrix 2965 2966 Output Parameter: 2967 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2968 2969 Level: intermediate 2970 2971 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2972 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2973 @*/ 2974 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2975 { 2976 PetscFunctionBegin; 2977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2978 PetscValidType(mat, 1); 2979 PetscAssertPointer(t, 2); 2980 *t = mat->factortype; 2981 PetscFunctionReturn(PETSC_SUCCESS); 2982 } 2983 2984 /*@ 2985 MatSetFactorType - sets the type of factorization a matrix is 2986 2987 Logically Collective 2988 2989 Input Parameters: 2990 + mat - the matrix 2991 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2992 2993 Level: intermediate 2994 2995 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2996 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2997 @*/ 2998 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2999 { 3000 PetscFunctionBegin; 3001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3002 PetscValidType(mat, 1); 3003 mat->factortype = t; 3004 PetscFunctionReturn(PETSC_SUCCESS); 3005 } 3006 3007 /*@ 3008 MatGetInfo - Returns information about matrix storage (number of 3009 nonzeros, memory, etc.). 3010 3011 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3012 3013 Input Parameters: 3014 + mat - the matrix 3015 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 3016 3017 Output Parameter: 3018 . info - matrix information context 3019 3020 Options Database Key: 3021 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3022 3023 Level: intermediate 3024 3025 Notes: 3026 The `MatInfo` context contains a variety of matrix data, including 3027 number of nonzeros allocated and used, number of mallocs during 3028 matrix assembly, etc. Additional information for factored matrices 3029 is provided (such as the fill ratio, number of mallocs during 3030 factorization, etc.). 3031 3032 Example: 3033 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3034 data within the `MatInfo` context. For example, 3035 .vb 3036 MatInfo info; 3037 Mat A; 3038 double mal, nz_a, nz_u; 3039 3040 MatGetInfo(A, MAT_LOCAL, &info); 3041 mal = info.mallocs; 3042 nz_a = info.nz_allocated; 3043 .ve 3044 3045 Fortran Note: 3046 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3047 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3048 a complete list of parameter names. 3049 .vb 3050 MatInfo info(MAT_INFO_SIZE) 3051 double precision mal, nz_a 3052 Mat A 3053 integer ierr 3054 3055 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3056 mal = info(MAT_INFO_MALLOCS) 3057 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3058 .ve 3059 3060 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3061 @*/ 3062 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3063 { 3064 PetscFunctionBegin; 3065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3066 PetscValidType(mat, 1); 3067 PetscAssertPointer(info, 3); 3068 MatCheckPreallocated(mat, 1); 3069 PetscUseTypeMethod(mat, getinfo, flag, info); 3070 PetscFunctionReturn(PETSC_SUCCESS); 3071 } 3072 3073 /* 3074 This is used by external packages where it is not easy to get the info from the actual 3075 matrix factorization. 3076 */ 3077 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3078 { 3079 PetscFunctionBegin; 3080 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3081 PetscFunctionReturn(PETSC_SUCCESS); 3082 } 3083 3084 /*@ 3085 MatLUFactor - Performs in-place LU factorization of matrix. 3086 3087 Collective 3088 3089 Input Parameters: 3090 + mat - the matrix 3091 . row - row permutation 3092 . col - column permutation 3093 - info - options for factorization, includes 3094 .vb 3095 fill - expected fill as ratio of original fill. 3096 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3097 Run with the option -info to determine an optimal value to use 3098 .ve 3099 3100 Level: developer 3101 3102 Notes: 3103 Most users should employ the `KSP` interface for linear solvers 3104 instead of working directly with matrix algebra routines such as this. 3105 See, e.g., `KSPCreate()`. 3106 3107 This changes the state of the matrix to a factored matrix; it cannot be used 3108 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3109 3110 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3111 when not using `KSP`. 3112 3113 Developer Note: 3114 The Fortran interface is not autogenerated as the 3115 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3116 3117 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3118 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3119 @*/ 3120 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3121 { 3122 MatFactorInfo tinfo; 3123 3124 PetscFunctionBegin; 3125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3126 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3127 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3128 if (info) PetscAssertPointer(info, 4); 3129 PetscValidType(mat, 1); 3130 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3131 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3132 MatCheckPreallocated(mat, 1); 3133 if (!info) { 3134 PetscCall(MatFactorInfoInitialize(&tinfo)); 3135 info = &tinfo; 3136 } 3137 3138 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3139 PetscUseTypeMethod(mat, lufactor, row, col, info); 3140 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3141 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3142 PetscFunctionReturn(PETSC_SUCCESS); 3143 } 3144 3145 /*@ 3146 MatILUFactor - Performs in-place ILU factorization of matrix. 3147 3148 Collective 3149 3150 Input Parameters: 3151 + mat - the matrix 3152 . row - row permutation 3153 . col - column permutation 3154 - info - structure containing 3155 .vb 3156 levels - number of levels of fill. 3157 expected fill - as ratio of original fill. 3158 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3159 missing diagonal entries) 3160 .ve 3161 3162 Level: developer 3163 3164 Notes: 3165 Most users should employ the `KSP` interface for linear solvers 3166 instead of working directly with matrix algebra routines such as this. 3167 See, e.g., `KSPCreate()`. 3168 3169 Probably really in-place only when level of fill is zero, otherwise allocates 3170 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3171 when not using `KSP`. 3172 3173 Developer Note: 3174 The Fortran interface is not autogenerated as the 3175 interface definition cannot be generated correctly [due to MatFactorInfo] 3176 3177 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3178 @*/ 3179 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3180 { 3181 PetscFunctionBegin; 3182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3183 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3184 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3185 PetscAssertPointer(info, 4); 3186 PetscValidType(mat, 1); 3187 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3188 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3189 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3190 MatCheckPreallocated(mat, 1); 3191 3192 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3193 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3194 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3195 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3196 PetscFunctionReturn(PETSC_SUCCESS); 3197 } 3198 3199 /*@ 3200 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3201 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3202 3203 Collective 3204 3205 Input Parameters: 3206 + fact - the factor matrix obtained with `MatGetFactor()` 3207 . mat - the matrix 3208 . row - the row permutation 3209 . col - the column permutation 3210 - info - options for factorization, includes 3211 .vb 3212 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3213 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3214 .ve 3215 3216 Level: developer 3217 3218 Notes: 3219 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3220 3221 Most users should employ the simplified `KSP` interface for linear solvers 3222 instead of working directly with matrix algebra routines such as this. 3223 See, e.g., `KSPCreate()`. 3224 3225 Developer Note: 3226 The Fortran interface is not autogenerated as the 3227 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3228 3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3230 @*/ 3231 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3232 { 3233 MatFactorInfo tinfo; 3234 3235 PetscFunctionBegin; 3236 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3238 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3239 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3240 if (info) PetscAssertPointer(info, 5); 3241 PetscValidType(fact, 1); 3242 PetscValidType(mat, 2); 3243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3244 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3245 MatCheckPreallocated(mat, 2); 3246 if (!info) { 3247 PetscCall(MatFactorInfoInitialize(&tinfo)); 3248 info = &tinfo; 3249 } 3250 3251 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3252 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3253 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3254 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3255 PetscFunctionReturn(PETSC_SUCCESS); 3256 } 3257 3258 /*@ 3259 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3260 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3261 3262 Collective 3263 3264 Input Parameters: 3265 + fact - the factor matrix obtained with `MatGetFactor()` 3266 . mat - the matrix 3267 - info - options for factorization 3268 3269 Level: developer 3270 3271 Notes: 3272 See `MatLUFactor()` for in-place factorization. See 3273 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3274 3275 Most users should employ the `KSP` interface for linear solvers 3276 instead of working directly with matrix algebra routines such as this. 3277 See, e.g., `KSPCreate()`. 3278 3279 Developer Note: 3280 The Fortran interface is not autogenerated as the 3281 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3282 3283 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3284 @*/ 3285 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3286 { 3287 MatFactorInfo tinfo; 3288 3289 PetscFunctionBegin; 3290 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3292 PetscValidType(fact, 1); 3293 PetscValidType(mat, 2); 3294 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3295 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3296 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3297 3298 MatCheckPreallocated(mat, 2); 3299 if (!info) { 3300 PetscCall(MatFactorInfoInitialize(&tinfo)); 3301 info = &tinfo; 3302 } 3303 3304 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3305 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3306 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3307 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3308 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3309 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3310 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3311 PetscFunctionReturn(PETSC_SUCCESS); 3312 } 3313 3314 /*@ 3315 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3316 symmetric matrix. 3317 3318 Collective 3319 3320 Input Parameters: 3321 + mat - the matrix 3322 . perm - row and column permutations 3323 - info - expected fill as ratio of original fill 3324 3325 Level: developer 3326 3327 Notes: 3328 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3329 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3330 3331 Most users should employ the `KSP` interface for linear solvers 3332 instead of working directly with matrix algebra routines such as this. 3333 See, e.g., `KSPCreate()`. 3334 3335 Developer Note: 3336 The Fortran interface is not autogenerated as the 3337 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3338 3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3340 `MatGetOrdering()` 3341 @*/ 3342 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3343 { 3344 MatFactorInfo tinfo; 3345 3346 PetscFunctionBegin; 3347 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3348 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3349 if (info) PetscAssertPointer(info, 3); 3350 PetscValidType(mat, 1); 3351 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3352 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3353 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3354 MatCheckPreallocated(mat, 1); 3355 if (!info) { 3356 PetscCall(MatFactorInfoInitialize(&tinfo)); 3357 info = &tinfo; 3358 } 3359 3360 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3361 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3362 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3363 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3364 PetscFunctionReturn(PETSC_SUCCESS); 3365 } 3366 3367 /*@ 3368 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3369 of a symmetric matrix. 3370 3371 Collective 3372 3373 Input Parameters: 3374 + fact - the factor matrix obtained with `MatGetFactor()` 3375 . mat - the matrix 3376 . perm - row and column permutations 3377 - info - options for factorization, includes 3378 .vb 3379 fill - expected fill as ratio of original fill. 3380 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3381 Run with the option -info to determine an optimal value to use 3382 .ve 3383 3384 Level: developer 3385 3386 Notes: 3387 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3388 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3389 3390 Most users should employ the `KSP` interface for linear solvers 3391 instead of working directly with matrix algebra routines such as this. 3392 See, e.g., `KSPCreate()`. 3393 3394 Developer Note: 3395 The Fortran interface is not autogenerated as the 3396 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3397 3398 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3399 `MatGetOrdering()` 3400 @*/ 3401 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3402 { 3403 MatFactorInfo tinfo; 3404 3405 PetscFunctionBegin; 3406 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3407 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3408 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3409 if (info) PetscAssertPointer(info, 4); 3410 PetscValidType(fact, 1); 3411 PetscValidType(mat, 2); 3412 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3413 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3414 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3415 MatCheckPreallocated(mat, 2); 3416 if (!info) { 3417 PetscCall(MatFactorInfoInitialize(&tinfo)); 3418 info = &tinfo; 3419 } 3420 3421 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3422 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3423 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3424 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3425 PetscFunctionReturn(PETSC_SUCCESS); 3426 } 3427 3428 /*@ 3429 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3430 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3431 `MatCholeskyFactorSymbolic()`. 3432 3433 Collective 3434 3435 Input Parameters: 3436 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3437 . mat - the initial matrix that is to be factored 3438 - info - options for factorization 3439 3440 Level: developer 3441 3442 Note: 3443 Most users should employ the `KSP` interface for linear solvers 3444 instead of working directly with matrix algebra routines such as this. 3445 See, e.g., `KSPCreate()`. 3446 3447 Developer Note: 3448 The Fortran interface is not autogenerated as the 3449 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3450 3451 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3452 @*/ 3453 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3454 { 3455 MatFactorInfo tinfo; 3456 3457 PetscFunctionBegin; 3458 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3460 PetscValidType(fact, 1); 3461 PetscValidType(mat, 2); 3462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3463 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3464 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3465 MatCheckPreallocated(mat, 2); 3466 if (!info) { 3467 PetscCall(MatFactorInfoInitialize(&tinfo)); 3468 info = &tinfo; 3469 } 3470 3471 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3472 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3473 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3474 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3475 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3476 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3477 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3478 PetscFunctionReturn(PETSC_SUCCESS); 3479 } 3480 3481 /*@ 3482 MatQRFactor - Performs in-place QR factorization of matrix. 3483 3484 Collective 3485 3486 Input Parameters: 3487 + mat - the matrix 3488 . col - column permutation 3489 - info - options for factorization, includes 3490 .vb 3491 fill - expected fill as ratio of original fill. 3492 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3493 Run with the option -info to determine an optimal value to use 3494 .ve 3495 3496 Level: developer 3497 3498 Notes: 3499 Most users should employ the `KSP` interface for linear solvers 3500 instead of working directly with matrix algebra routines such as this. 3501 See, e.g., `KSPCreate()`. 3502 3503 This changes the state of the matrix to a factored matrix; it cannot be used 3504 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3505 3506 Developer Note: 3507 The Fortran interface is not autogenerated as the 3508 interface definition cannot be generated correctly [due to MatFactorInfo] 3509 3510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3511 `MatSetUnfactored()` 3512 @*/ 3513 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3514 { 3515 PetscFunctionBegin; 3516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3517 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3518 if (info) PetscAssertPointer(info, 3); 3519 PetscValidType(mat, 1); 3520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3522 MatCheckPreallocated(mat, 1); 3523 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3524 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3525 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3526 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3527 PetscFunctionReturn(PETSC_SUCCESS); 3528 } 3529 3530 /*@ 3531 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3532 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3533 3534 Collective 3535 3536 Input Parameters: 3537 + fact - the factor matrix obtained with `MatGetFactor()` 3538 . mat - the matrix 3539 . col - column permutation 3540 - info - options for factorization, includes 3541 .vb 3542 fill - expected fill as ratio of original fill. 3543 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3544 Run with the option -info to determine an optimal value to use 3545 .ve 3546 3547 Level: developer 3548 3549 Note: 3550 Most users should employ the `KSP` interface for linear solvers 3551 instead of working directly with matrix algebra routines such as this. 3552 See, e.g., `KSPCreate()`. 3553 3554 Developer Note: 3555 The Fortran interface is not autogenerated as the 3556 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3557 3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3559 @*/ 3560 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3561 { 3562 MatFactorInfo tinfo; 3563 3564 PetscFunctionBegin; 3565 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3567 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3568 if (info) PetscAssertPointer(info, 4); 3569 PetscValidType(fact, 1); 3570 PetscValidType(mat, 2); 3571 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3572 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3573 MatCheckPreallocated(mat, 2); 3574 if (!info) { 3575 PetscCall(MatFactorInfoInitialize(&tinfo)); 3576 info = &tinfo; 3577 } 3578 3579 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3580 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3581 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3582 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3583 PetscFunctionReturn(PETSC_SUCCESS); 3584 } 3585 3586 /*@ 3587 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3588 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3589 3590 Collective 3591 3592 Input Parameters: 3593 + fact - the factor matrix obtained with `MatGetFactor()` 3594 . mat - the matrix 3595 - info - options for factorization 3596 3597 Level: developer 3598 3599 Notes: 3600 See `MatQRFactor()` for in-place factorization. 3601 3602 Most users should employ the `KSP` interface for linear solvers 3603 instead of working directly with matrix algebra routines such as this. 3604 See, e.g., `KSPCreate()`. 3605 3606 Developer Note: 3607 The Fortran interface is not autogenerated as the 3608 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3609 3610 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3611 @*/ 3612 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3613 { 3614 MatFactorInfo tinfo; 3615 3616 PetscFunctionBegin; 3617 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3619 PetscValidType(fact, 1); 3620 PetscValidType(mat, 2); 3621 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3622 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3623 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3624 3625 MatCheckPreallocated(mat, 2); 3626 if (!info) { 3627 PetscCall(MatFactorInfoInitialize(&tinfo)); 3628 info = &tinfo; 3629 } 3630 3631 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3632 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3633 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3634 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3635 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3636 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3637 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 3641 /*@ 3642 MatSolve - Solves $A x = b$, given a factored matrix. 3643 3644 Neighbor-wise Collective 3645 3646 Input Parameters: 3647 + mat - the factored matrix 3648 - b - the right-hand-side vector 3649 3650 Output Parameter: 3651 . x - the result vector 3652 3653 Level: developer 3654 3655 Notes: 3656 The vectors `b` and `x` cannot be the same. I.e., one cannot 3657 call `MatSolve`(A,x,x). 3658 3659 Most users should employ the `KSP` interface for linear solvers 3660 instead of working directly with matrix algebra routines such as this. 3661 See, e.g., `KSPCreate()`. 3662 3663 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3664 @*/ 3665 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3666 { 3667 PetscFunctionBegin; 3668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3669 PetscValidType(mat, 1); 3670 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3671 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3672 PetscCheckSameComm(mat, 1, b, 2); 3673 PetscCheckSameComm(mat, 1, x, 3); 3674 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3675 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3676 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3677 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3678 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3679 MatCheckPreallocated(mat, 1); 3680 3681 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3682 PetscCall(VecFlag(x, mat->factorerrortype)); 3683 if (mat->factorerrortype) { 3684 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3685 } else PetscUseTypeMethod(mat, solve, b, x); 3686 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3687 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3688 PetscFunctionReturn(PETSC_SUCCESS); 3689 } 3690 3691 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3692 { 3693 Vec b, x; 3694 PetscInt N, i; 3695 PetscErrorCode (*f)(Mat, Vec, Vec); 3696 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3697 3698 PetscFunctionBegin; 3699 if (A->factorerrortype) { 3700 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3701 PetscCall(MatSetInf(X)); 3702 PetscFunctionReturn(PETSC_SUCCESS); 3703 } 3704 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3705 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3706 PetscCall(MatBoundToCPU(A, &Abound)); 3707 if (!Abound) { 3708 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3709 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3710 } 3711 #if PetscDefined(HAVE_CUDA) 3712 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3713 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3714 #elif PetscDefined(HAVE_HIP) 3715 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3716 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3717 #endif 3718 PetscCall(MatGetSize(B, NULL, &N)); 3719 for (i = 0; i < N; i++) { 3720 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3721 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3722 PetscCall((*f)(A, b, x)); 3723 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3724 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3725 } 3726 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3727 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3728 PetscFunctionReturn(PETSC_SUCCESS); 3729 } 3730 3731 /*@ 3732 MatMatSolve - Solves $A X = B$, given a factored matrix. 3733 3734 Neighbor-wise Collective 3735 3736 Input Parameters: 3737 + A - the factored matrix 3738 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3739 3740 Output Parameter: 3741 . X - the result matrix (dense matrix) 3742 3743 Level: developer 3744 3745 Note: 3746 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3747 otherwise, `B` and `X` cannot be the same. 3748 3749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3750 @*/ 3751 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3752 { 3753 PetscFunctionBegin; 3754 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3755 PetscValidType(A, 1); 3756 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3757 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3758 PetscCheckSameComm(A, 1, B, 2); 3759 PetscCheckSameComm(A, 1, X, 3); 3760 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3761 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3762 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3763 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3764 MatCheckPreallocated(A, 1); 3765 3766 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3767 if (!A->ops->matsolve) { 3768 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3769 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3770 } else PetscUseTypeMethod(A, matsolve, B, X); 3771 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3772 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3773 PetscFunctionReturn(PETSC_SUCCESS); 3774 } 3775 3776 /*@ 3777 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3778 3779 Neighbor-wise Collective 3780 3781 Input Parameters: 3782 + A - the factored matrix 3783 - B - the right-hand-side matrix (`MATDENSE` matrix) 3784 3785 Output Parameter: 3786 . X - the result matrix (dense matrix) 3787 3788 Level: developer 3789 3790 Note: 3791 The matrices `B` and `X` cannot be the same. I.e., one cannot 3792 call `MatMatSolveTranspose`(A,X,X). 3793 3794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3795 @*/ 3796 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3797 { 3798 PetscFunctionBegin; 3799 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3800 PetscValidType(A, 1); 3801 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3802 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3803 PetscCheckSameComm(A, 1, B, 2); 3804 PetscCheckSameComm(A, 1, X, 3); 3805 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3806 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3807 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3808 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3809 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3810 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3811 MatCheckPreallocated(A, 1); 3812 3813 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3814 if (!A->ops->matsolvetranspose) { 3815 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3816 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3817 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3818 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3819 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3820 PetscFunctionReturn(PETSC_SUCCESS); 3821 } 3822 3823 /*@ 3824 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3825 3826 Neighbor-wise Collective 3827 3828 Input Parameters: 3829 + A - the factored matrix 3830 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3831 3832 Output Parameter: 3833 . X - the result matrix (dense matrix) 3834 3835 Level: developer 3836 3837 Note: 3838 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right-hand side matrix. User must create `Bt` in sparse compressed row 3839 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3840 3841 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3842 @*/ 3843 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3844 { 3845 PetscFunctionBegin; 3846 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3847 PetscValidType(A, 1); 3848 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3849 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3850 PetscCheckSameComm(A, 1, Bt, 2); 3851 PetscCheckSameComm(A, 1, X, 3); 3852 3853 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3854 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3855 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3856 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3857 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3858 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3859 MatCheckPreallocated(A, 1); 3860 3861 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3862 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3863 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3864 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3865 PetscFunctionReturn(PETSC_SUCCESS); 3866 } 3867 3868 /*@ 3869 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3870 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3871 3872 Neighbor-wise Collective 3873 3874 Input Parameters: 3875 + mat - the factored matrix 3876 - b - the right-hand-side vector 3877 3878 Output Parameter: 3879 . x - the result vector 3880 3881 Level: developer 3882 3883 Notes: 3884 `MatSolve()` should be used for most applications, as it performs 3885 a forward solve followed by a backward solve. 3886 3887 The vectors `b` and `x` cannot be the same, i.e., one cannot 3888 call `MatForwardSolve`(A,x,x). 3889 3890 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3891 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3892 `MatForwardSolve()` solves $U^T*D y = b$, and 3893 `MatBackwardSolve()` solves $U x = y$. 3894 Thus they do not provide a symmetric preconditioner. 3895 3896 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3897 @*/ 3898 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3899 { 3900 PetscFunctionBegin; 3901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3902 PetscValidType(mat, 1); 3903 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3904 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3905 PetscCheckSameComm(mat, 1, b, 2); 3906 PetscCheckSameComm(mat, 1, x, 3); 3907 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3908 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3909 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3910 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3911 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3912 MatCheckPreallocated(mat, 1); 3913 3914 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3915 PetscUseTypeMethod(mat, forwardsolve, b, x); 3916 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3917 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3918 PetscFunctionReturn(PETSC_SUCCESS); 3919 } 3920 3921 /*@ 3922 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3923 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3924 3925 Neighbor-wise Collective 3926 3927 Input Parameters: 3928 + mat - the factored matrix 3929 - b - the right-hand-side vector 3930 3931 Output Parameter: 3932 . x - the result vector 3933 3934 Level: developer 3935 3936 Notes: 3937 `MatSolve()` should be used for most applications, as it performs 3938 a forward solve followed by a backward solve. 3939 3940 The vectors `b` and `x` cannot be the same. I.e., one cannot 3941 call `MatBackwardSolve`(A,x,x). 3942 3943 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3944 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3945 `MatForwardSolve()` solves $U^T*D y = b$, and 3946 `MatBackwardSolve()` solves $U x = y$. 3947 Thus they do not provide a symmetric preconditioner. 3948 3949 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3950 @*/ 3951 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3952 { 3953 PetscFunctionBegin; 3954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3955 PetscValidType(mat, 1); 3956 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3957 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3958 PetscCheckSameComm(mat, 1, b, 2); 3959 PetscCheckSameComm(mat, 1, x, 3); 3960 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3961 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3962 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3963 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3964 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3965 MatCheckPreallocated(mat, 1); 3966 3967 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3968 PetscUseTypeMethod(mat, backwardsolve, b, x); 3969 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3970 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3971 PetscFunctionReturn(PETSC_SUCCESS); 3972 } 3973 3974 /*@ 3975 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3976 3977 Neighbor-wise Collective 3978 3979 Input Parameters: 3980 + mat - the factored matrix 3981 . b - the right-hand-side vector 3982 - y - the vector to be added to 3983 3984 Output Parameter: 3985 . x - the result vector 3986 3987 Level: developer 3988 3989 Note: 3990 The vectors `b` and `x` cannot be the same. I.e., one cannot 3991 call `MatSolveAdd`(A,x,y,x). 3992 3993 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3994 @*/ 3995 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3996 { 3997 PetscScalar one = 1.0; 3998 Vec tmp; 3999 4000 PetscFunctionBegin; 4001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4002 PetscValidType(mat, 1); 4003 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4004 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4005 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4006 PetscCheckSameComm(mat, 1, b, 2); 4007 PetscCheckSameComm(mat, 1, y, 3); 4008 PetscCheckSameComm(mat, 1, x, 4); 4009 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4010 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4011 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4012 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 4013 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4014 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4015 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4016 MatCheckPreallocated(mat, 1); 4017 4018 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4019 PetscCall(VecFlag(x, mat->factorerrortype)); 4020 if (mat->factorerrortype) { 4021 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4022 } else if (mat->ops->solveadd) { 4023 PetscUseTypeMethod(mat, solveadd, b, y, x); 4024 } else { 4025 /* do the solve then the add manually */ 4026 if (x != y) { 4027 PetscCall(MatSolve(mat, b, x)); 4028 PetscCall(VecAXPY(x, one, y)); 4029 } else { 4030 PetscCall(VecDuplicate(x, &tmp)); 4031 PetscCall(VecCopy(x, tmp)); 4032 PetscCall(MatSolve(mat, b, x)); 4033 PetscCall(VecAXPY(x, one, tmp)); 4034 PetscCall(VecDestroy(&tmp)); 4035 } 4036 } 4037 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4038 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4039 PetscFunctionReturn(PETSC_SUCCESS); 4040 } 4041 4042 /*@ 4043 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4044 4045 Neighbor-wise Collective 4046 4047 Input Parameters: 4048 + mat - the factored matrix 4049 - b - the right-hand-side vector 4050 4051 Output Parameter: 4052 . x - the result vector 4053 4054 Level: developer 4055 4056 Notes: 4057 The vectors `b` and `x` cannot be the same. I.e., one cannot 4058 call `MatSolveTranspose`(A,x,x). 4059 4060 Most users should employ the `KSP` interface for linear solvers 4061 instead of working directly with matrix algebra routines such as this. 4062 See, e.g., `KSPCreate()`. 4063 4064 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4065 @*/ 4066 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4067 { 4068 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4069 4070 PetscFunctionBegin; 4071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4072 PetscValidType(mat, 1); 4073 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4074 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4075 PetscCheckSameComm(mat, 1, b, 2); 4076 PetscCheckSameComm(mat, 1, x, 3); 4077 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4078 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4079 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4080 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4081 MatCheckPreallocated(mat, 1); 4082 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4083 PetscCall(VecFlag(x, mat->factorerrortype)); 4084 if (mat->factorerrortype) { 4085 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4086 } else { 4087 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4088 PetscCall((*f)(mat, b, x)); 4089 } 4090 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4091 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4092 PetscFunctionReturn(PETSC_SUCCESS); 4093 } 4094 4095 /*@ 4096 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4097 factored matrix. 4098 4099 Neighbor-wise Collective 4100 4101 Input Parameters: 4102 + mat - the factored matrix 4103 . b - the right-hand-side vector 4104 - y - the vector to be added to 4105 4106 Output Parameter: 4107 . x - the result vector 4108 4109 Level: developer 4110 4111 Note: 4112 The vectors `b` and `x` cannot be the same. I.e., one cannot 4113 call `MatSolveTransposeAdd`(A,x,y,x). 4114 4115 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4116 @*/ 4117 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4118 { 4119 PetscScalar one = 1.0; 4120 Vec tmp; 4121 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4122 4123 PetscFunctionBegin; 4124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4125 PetscValidType(mat, 1); 4126 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4127 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4128 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4129 PetscCheckSameComm(mat, 1, b, 2); 4130 PetscCheckSameComm(mat, 1, y, 3); 4131 PetscCheckSameComm(mat, 1, x, 4); 4132 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4133 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4134 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4135 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4136 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4137 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4138 MatCheckPreallocated(mat, 1); 4139 4140 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4141 PetscCall(VecFlag(x, mat->factorerrortype)); 4142 if (mat->factorerrortype) { 4143 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4144 } else if (f) { 4145 PetscCall((*f)(mat, b, y, x)); 4146 } else { 4147 /* do the solve then the add manually */ 4148 if (x != y) { 4149 PetscCall(MatSolveTranspose(mat, b, x)); 4150 PetscCall(VecAXPY(x, one, y)); 4151 } else { 4152 PetscCall(VecDuplicate(x, &tmp)); 4153 PetscCall(VecCopy(x, tmp)); 4154 PetscCall(MatSolveTranspose(mat, b, x)); 4155 PetscCall(VecAXPY(x, one, tmp)); 4156 PetscCall(VecDestroy(&tmp)); 4157 } 4158 } 4159 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4160 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4161 PetscFunctionReturn(PETSC_SUCCESS); 4162 } 4163 4164 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4165 /*@ 4166 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4167 4168 Neighbor-wise Collective 4169 4170 Input Parameters: 4171 + mat - the matrix 4172 . b - the right-hand side 4173 . omega - the relaxation factor 4174 . flag - flag indicating the type of SOR (see below) 4175 . shift - diagonal shift 4176 . its - the number of iterations 4177 - lits - the number of local iterations 4178 4179 Output Parameter: 4180 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4181 4182 SOR Flags: 4183 + `SOR_FORWARD_SWEEP` - forward SOR 4184 . `SOR_BACKWARD_SWEEP` - backward SOR 4185 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4186 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4187 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4188 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4189 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4190 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4191 upper/lower triangular part of matrix to 4192 vector (with omega) 4193 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4194 4195 Level: developer 4196 4197 Notes: 4198 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4199 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4200 on each processor. 4201 4202 Application programmers will not generally use `MatSOR()` directly, 4203 but instead will employ the `KSP`/`PC` interface. 4204 4205 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4206 4207 Most users should employ the `KSP` interface for linear solvers 4208 instead of working directly with matrix algebra routines such as this. 4209 See, e.g., `KSPCreate()`. 4210 4211 Vectors `x` and `b` CANNOT be the same 4212 4213 The flags are implemented as bitwise inclusive or operations. 4214 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4215 to specify a zero initial guess for SSOR. 4216 4217 Developer Note: 4218 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4219 4220 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4221 @*/ 4222 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4223 { 4224 PetscFunctionBegin; 4225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4226 PetscValidType(mat, 1); 4227 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4228 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4229 PetscCheckSameComm(mat, 1, b, 2); 4230 PetscCheckSameComm(mat, 1, x, 8); 4231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4232 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4233 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4234 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4235 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4236 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4237 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4238 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4239 4240 MatCheckPreallocated(mat, 1); 4241 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4242 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4243 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4244 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4245 PetscFunctionReturn(PETSC_SUCCESS); 4246 } 4247 4248 /* 4249 Default matrix copy routine. 4250 */ 4251 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4252 { 4253 PetscInt i, rstart = 0, rend = 0, nz; 4254 const PetscInt *cwork; 4255 const PetscScalar *vwork; 4256 4257 PetscFunctionBegin; 4258 if (B->assembled) PetscCall(MatZeroEntries(B)); 4259 if (str == SAME_NONZERO_PATTERN) { 4260 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4261 for (i = rstart; i < rend; i++) { 4262 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4263 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4264 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4265 } 4266 } else { 4267 PetscCall(MatAYPX(B, 0.0, A, str)); 4268 } 4269 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4270 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4271 PetscFunctionReturn(PETSC_SUCCESS); 4272 } 4273 4274 /*@ 4275 MatCopy - Copies a matrix to another matrix. 4276 4277 Collective 4278 4279 Input Parameters: 4280 + A - the matrix 4281 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4282 4283 Output Parameter: 4284 . B - where the copy is put 4285 4286 Level: intermediate 4287 4288 Notes: 4289 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4290 4291 `MatCopy()` copies the matrix entries of a matrix to another existing 4292 matrix (after first zeroing the second matrix). A related routine is 4293 `MatConvert()`, which first creates a new matrix and then copies the data. 4294 4295 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4296 @*/ 4297 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4298 { 4299 PetscInt i; 4300 4301 PetscFunctionBegin; 4302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4303 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4304 PetscValidType(A, 1); 4305 PetscValidType(B, 2); 4306 PetscCheckSameComm(A, 1, B, 2); 4307 MatCheckPreallocated(B, 2); 4308 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4309 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4310 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4311 A->cmap->N, B->cmap->N); 4312 MatCheckPreallocated(A, 1); 4313 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4314 4315 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4316 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4317 else PetscCall(MatCopy_Basic(A, B, str)); 4318 4319 B->stencil.dim = A->stencil.dim; 4320 B->stencil.noc = A->stencil.noc; 4321 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4322 B->stencil.dims[i] = A->stencil.dims[i]; 4323 B->stencil.starts[i] = A->stencil.starts[i]; 4324 } 4325 4326 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4327 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4328 PetscFunctionReturn(PETSC_SUCCESS); 4329 } 4330 4331 /*@ 4332 MatConvert - Converts a matrix to another matrix, either of the same 4333 or different type. 4334 4335 Collective 4336 4337 Input Parameters: 4338 + mat - the matrix 4339 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4340 same type as the original matrix. 4341 - reuse - denotes if the destination matrix is to be created or reused. 4342 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use 4343 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused). 4344 4345 Output Parameter: 4346 . M - pointer to place new matrix 4347 4348 Level: intermediate 4349 4350 Notes: 4351 `MatConvert()` first creates a new matrix and then copies the data from 4352 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4353 entries of one matrix to another already existing matrix context. 4354 4355 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4356 the MPI communicator of the generated matrix is always the same as the communicator 4357 of the input matrix. 4358 4359 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4360 @*/ 4361 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4362 { 4363 PetscBool sametype, issame, flg; 4364 PetscBool3 issymmetric, ishermitian; 4365 char convname[256], mtype[256]; 4366 Mat B; 4367 4368 PetscFunctionBegin; 4369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4370 PetscValidType(mat, 1); 4371 PetscAssertPointer(M, 4); 4372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4373 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4374 MatCheckPreallocated(mat, 1); 4375 4376 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4377 if (flg) newtype = mtype; 4378 4379 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4380 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4381 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4382 if (reuse == MAT_REUSE_MATRIX) { 4383 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4384 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4385 } 4386 4387 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4388 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4389 PetscFunctionReturn(PETSC_SUCCESS); 4390 } 4391 4392 /* Cache Mat options because some converters use MatHeaderReplace */ 4393 issymmetric = mat->symmetric; 4394 ishermitian = mat->hermitian; 4395 4396 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4397 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4398 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4399 } else { 4400 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4401 const char *prefix[3] = {"seq", "mpi", ""}; 4402 PetscInt i; 4403 /* 4404 Order of precedence: 4405 0) See if newtype is a superclass of the current matrix. 4406 1) See if a specialized converter is known to the current matrix. 4407 2) See if a specialized converter is known to the desired matrix class. 4408 3) See if a good general converter is registered for the desired class 4409 (as of 6/27/03 only MATMPIADJ falls into this category). 4410 4) See if a good general converter is known for the current matrix. 4411 5) Use a really basic converter. 4412 */ 4413 4414 /* 0) See if newtype is a superclass of the current matrix. 4415 i.e mat is mpiaij and newtype is aij */ 4416 for (i = 0; i < 2; i++) { 4417 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4418 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4419 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4420 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4421 if (flg) { 4422 if (reuse == MAT_INPLACE_MATRIX) { 4423 PetscCall(PetscInfo(mat, "Early return\n")); 4424 PetscFunctionReturn(PETSC_SUCCESS); 4425 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4426 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4427 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4428 PetscFunctionReturn(PETSC_SUCCESS); 4429 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4430 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4431 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4432 PetscFunctionReturn(PETSC_SUCCESS); 4433 } 4434 } 4435 } 4436 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4437 for (i = 0; i < 3; i++) { 4438 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4439 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4440 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4441 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4443 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4444 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4445 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4446 if (conv) goto foundconv; 4447 } 4448 4449 /* 2) See if a specialized converter is known to the desired matrix class. */ 4450 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4451 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4452 PetscCall(MatSetType(B, newtype)); 4453 for (i = 0; i < 3; i++) { 4454 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4455 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4456 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4457 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4458 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4459 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4460 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4461 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4462 if (conv) { 4463 PetscCall(MatDestroy(&B)); 4464 goto foundconv; 4465 } 4466 } 4467 4468 /* 3) See if a good general converter is registered for the desired class */ 4469 conv = B->ops->convertfrom; 4470 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4471 PetscCall(MatDestroy(&B)); 4472 if (conv) goto foundconv; 4473 4474 /* 4) See if a good general converter is known for the current matrix */ 4475 if (mat->ops->convert) conv = mat->ops->convert; 4476 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4477 if (conv) goto foundconv; 4478 4479 /* 5) Use a really basic converter. */ 4480 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4481 conv = MatConvert_Basic; 4482 4483 foundconv: 4484 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4485 PetscCall((*conv)(mat, newtype, reuse, M)); 4486 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4487 /* the block sizes must be same if the mappings are copied over */ 4488 (*M)->rmap->bs = mat->rmap->bs; 4489 (*M)->cmap->bs = mat->cmap->bs; 4490 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4491 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4492 (*M)->rmap->mapping = mat->rmap->mapping; 4493 (*M)->cmap->mapping = mat->cmap->mapping; 4494 } 4495 (*M)->stencil.dim = mat->stencil.dim; 4496 (*M)->stencil.noc = mat->stencil.noc; 4497 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4498 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4499 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4500 } 4501 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4502 } 4503 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4504 4505 /* Copy Mat options */ 4506 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4507 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4508 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4509 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4510 PetscFunctionReturn(PETSC_SUCCESS); 4511 } 4512 4513 /*@ 4514 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4515 4516 Not Collective 4517 4518 Input Parameter: 4519 . mat - the matrix, must be a factored matrix 4520 4521 Output Parameter: 4522 . type - the string name of the package (do not free this string) 4523 4524 Level: intermediate 4525 4526 Fortran Note: 4527 Pass in an empty string that is long enough and the package name will be copied into it. 4528 4529 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4530 @*/ 4531 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4532 { 4533 PetscErrorCode (*conv)(Mat, MatSolverType *); 4534 4535 PetscFunctionBegin; 4536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4537 PetscValidType(mat, 1); 4538 PetscAssertPointer(type, 2); 4539 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4540 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4541 if (conv) PetscCall((*conv)(mat, type)); 4542 else *type = MATSOLVERPETSC; 4543 PetscFunctionReturn(PETSC_SUCCESS); 4544 } 4545 4546 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4547 struct _MatSolverTypeForSpecifcType { 4548 MatType mtype; 4549 /* no entry for MAT_FACTOR_NONE */ 4550 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4551 MatSolverTypeForSpecifcType next; 4552 }; 4553 4554 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4555 struct _MatSolverTypeHolder { 4556 char *name; 4557 MatSolverTypeForSpecifcType handlers; 4558 MatSolverTypeHolder next; 4559 }; 4560 4561 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4562 4563 /*@C 4564 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4565 4566 Logically Collective, No Fortran Support 4567 4568 Input Parameters: 4569 + package - name of the package, for example petsc or superlu 4570 . mtype - the matrix type that works with this package 4571 . ftype - the type of factorization supported by the package 4572 - createfactor - routine that will create the factored matrix ready to be used 4573 4574 Level: developer 4575 4576 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4577 `MatGetFactor()` 4578 @*/ 4579 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4580 { 4581 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4582 PetscBool flg; 4583 MatSolverTypeForSpecifcType inext, iprev = NULL; 4584 4585 PetscFunctionBegin; 4586 PetscCall(MatInitializePackage()); 4587 if (!next) { 4588 PetscCall(PetscNew(&MatSolverTypeHolders)); 4589 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4590 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4591 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4592 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4593 PetscFunctionReturn(PETSC_SUCCESS); 4594 } 4595 while (next) { 4596 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4597 if (flg) { 4598 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4599 inext = next->handlers; 4600 while (inext) { 4601 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4602 if (flg) { 4603 inext->createfactor[(int)ftype - 1] = createfactor; 4604 PetscFunctionReturn(PETSC_SUCCESS); 4605 } 4606 iprev = inext; 4607 inext = inext->next; 4608 } 4609 PetscCall(PetscNew(&iprev->next)); 4610 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4611 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4612 PetscFunctionReturn(PETSC_SUCCESS); 4613 } 4614 prev = next; 4615 next = next->next; 4616 } 4617 PetscCall(PetscNew(&prev->next)); 4618 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4619 PetscCall(PetscNew(&prev->next->handlers)); 4620 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4621 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4622 PetscFunctionReturn(PETSC_SUCCESS); 4623 } 4624 4625 /*@C 4626 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4627 4628 Input Parameters: 4629 + type - name of the package, for example petsc or superlu, if this is 'NULL', then the first result that satisfies the other criteria is returned 4630 . ftype - the type of factorization supported by the type 4631 - mtype - the matrix type that works with this type 4632 4633 Output Parameters: 4634 + foundtype - `PETSC_TRUE` if the type was registered 4635 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4636 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4637 4638 Calling sequence of `createfactor`: 4639 + A - the matrix providing the factor matrix 4640 . ftype - the `MatFactorType` of the factor requested 4641 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4642 4643 Level: developer 4644 4645 Note: 4646 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4647 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4648 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4649 4650 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4651 `MatInitializePackage()` 4652 @*/ 4653 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4654 { 4655 MatSolverTypeHolder next = MatSolverTypeHolders; 4656 PetscBool flg; 4657 MatSolverTypeForSpecifcType inext; 4658 4659 PetscFunctionBegin; 4660 if (foundtype) *foundtype = PETSC_FALSE; 4661 if (foundmtype) *foundmtype = PETSC_FALSE; 4662 if (createfactor) *createfactor = NULL; 4663 4664 if (type) { 4665 while (next) { 4666 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4667 if (flg) { 4668 if (foundtype) *foundtype = PETSC_TRUE; 4669 inext = next->handlers; 4670 while (inext) { 4671 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4672 if (flg) { 4673 if (foundmtype) *foundmtype = PETSC_TRUE; 4674 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4675 PetscFunctionReturn(PETSC_SUCCESS); 4676 } 4677 inext = inext->next; 4678 } 4679 } 4680 next = next->next; 4681 } 4682 } else { 4683 while (next) { 4684 inext = next->handlers; 4685 while (inext) { 4686 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4687 if (flg && inext->createfactor[(int)ftype - 1]) { 4688 if (foundtype) *foundtype = PETSC_TRUE; 4689 if (foundmtype) *foundmtype = PETSC_TRUE; 4690 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4691 PetscFunctionReturn(PETSC_SUCCESS); 4692 } 4693 inext = inext->next; 4694 } 4695 next = next->next; 4696 } 4697 /* try with base classes inext->mtype */ 4698 next = MatSolverTypeHolders; 4699 while (next) { 4700 inext = next->handlers; 4701 while (inext) { 4702 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4703 if (flg && inext->createfactor[(int)ftype - 1]) { 4704 if (foundtype) *foundtype = PETSC_TRUE; 4705 if (foundmtype) *foundmtype = PETSC_TRUE; 4706 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4707 PetscFunctionReturn(PETSC_SUCCESS); 4708 } 4709 inext = inext->next; 4710 } 4711 next = next->next; 4712 } 4713 } 4714 PetscFunctionReturn(PETSC_SUCCESS); 4715 } 4716 4717 PetscErrorCode MatSolverTypeDestroy(void) 4718 { 4719 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4720 MatSolverTypeForSpecifcType inext, iprev; 4721 4722 PetscFunctionBegin; 4723 while (next) { 4724 PetscCall(PetscFree(next->name)); 4725 inext = next->handlers; 4726 while (inext) { 4727 PetscCall(PetscFree(inext->mtype)); 4728 iprev = inext; 4729 inext = inext->next; 4730 PetscCall(PetscFree(iprev)); 4731 } 4732 prev = next; 4733 next = next->next; 4734 PetscCall(PetscFree(prev)); 4735 } 4736 MatSolverTypeHolders = NULL; 4737 PetscFunctionReturn(PETSC_SUCCESS); 4738 } 4739 4740 /*@ 4741 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4742 4743 Logically Collective 4744 4745 Input Parameter: 4746 . mat - the matrix 4747 4748 Output Parameter: 4749 . flg - `PETSC_TRUE` if uses the ordering 4750 4751 Level: developer 4752 4753 Note: 4754 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4755 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4756 4757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4758 @*/ 4759 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4760 { 4761 PetscFunctionBegin; 4762 *flg = mat->canuseordering; 4763 PetscFunctionReturn(PETSC_SUCCESS); 4764 } 4765 4766 /*@ 4767 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4768 4769 Logically Collective 4770 4771 Input Parameters: 4772 + mat - the matrix obtained with `MatGetFactor()` 4773 - ftype - the factorization type to be used 4774 4775 Output Parameter: 4776 . otype - the preferred ordering type 4777 4778 Level: developer 4779 4780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4781 @*/ 4782 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4783 { 4784 PetscFunctionBegin; 4785 *otype = mat->preferredordering[ftype]; 4786 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4787 PetscFunctionReturn(PETSC_SUCCESS); 4788 } 4789 4790 /*@ 4791 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4792 4793 Collective 4794 4795 Input Parameters: 4796 + mat - the matrix 4797 . type - name of solver type, for example, superlu, petsc (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies 4798 the other criteria is returned 4799 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4800 4801 Output Parameter: 4802 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4803 4804 Options Database Keys: 4805 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4806 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4807 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4808 4809 Level: intermediate 4810 4811 Notes: 4812 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4813 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4814 4815 Users usually access the factorization solvers via `KSP` 4816 4817 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4818 such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir 4819 4820 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4821 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4822 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4823 4824 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4825 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4826 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4827 4828 Developer Note: 4829 This should actually be called `MatCreateFactor()` since it creates a new factor object 4830 4831 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4832 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4833 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4834 @*/ 4835 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4836 { 4837 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4838 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4839 4840 PetscFunctionBegin; 4841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4842 PetscValidType(mat, 1); 4843 4844 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4845 MatCheckPreallocated(mat, 1); 4846 4847 PetscCall(MatIsShell(mat, &shell)); 4848 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4849 if (hasop) { 4850 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4851 PetscFunctionReturn(PETSC_SUCCESS); 4852 } 4853 4854 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4855 if (!foundtype) { 4856 if (type) { 4857 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype], 4858 ((PetscObject)mat)->type_name, type); 4859 } else { 4860 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4861 } 4862 } 4863 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4864 PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4865 4866 PetscCall((*conv)(mat, ftype, f)); 4867 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4868 PetscFunctionReturn(PETSC_SUCCESS); 4869 } 4870 4871 /*@ 4872 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4873 4874 Not Collective 4875 4876 Input Parameters: 4877 + mat - the matrix 4878 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4879 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4880 4881 Output Parameter: 4882 . flg - PETSC_TRUE if the factorization is available 4883 4884 Level: intermediate 4885 4886 Notes: 4887 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4888 such as pastix, superlu, mumps etc. 4889 4890 PETSc must have been ./configure to use the external solver, using the option --download-package 4891 4892 Developer Note: 4893 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4894 4895 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4896 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4897 @*/ 4898 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4899 { 4900 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4901 4902 PetscFunctionBegin; 4903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4904 PetscAssertPointer(flg, 4); 4905 4906 *flg = PETSC_FALSE; 4907 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4908 4909 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4910 MatCheckPreallocated(mat, 1); 4911 4912 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4913 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4914 PetscFunctionReturn(PETSC_SUCCESS); 4915 } 4916 4917 /*@ 4918 MatDuplicate - Duplicates a matrix including the non-zero structure. 4919 4920 Collective 4921 4922 Input Parameters: 4923 + mat - the matrix 4924 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4925 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4926 4927 Output Parameter: 4928 . M - pointer to place new matrix 4929 4930 Level: intermediate 4931 4932 Notes: 4933 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4934 4935 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4936 4937 May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well. 4938 4939 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4940 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4941 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4942 4943 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4944 @*/ 4945 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4946 { 4947 Mat B; 4948 VecType vtype; 4949 PetscInt i; 4950 PetscObject dm, container_h, container_d; 4951 void (*viewf)(void); 4952 4953 PetscFunctionBegin; 4954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4955 PetscValidType(mat, 1); 4956 PetscAssertPointer(M, 3); 4957 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4958 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4959 MatCheckPreallocated(mat, 1); 4960 4961 *M = NULL; 4962 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4963 PetscUseTypeMethod(mat, duplicate, op, M); 4964 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4965 B = *M; 4966 4967 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4968 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4969 PetscCall(MatGetVecType(mat, &vtype)); 4970 PetscCall(MatSetVecType(B, vtype)); 4971 4972 B->stencil.dim = mat->stencil.dim; 4973 B->stencil.noc = mat->stencil.noc; 4974 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4975 B->stencil.dims[i] = mat->stencil.dims[i]; 4976 B->stencil.starts[i] = mat->stencil.starts[i]; 4977 } 4978 4979 B->nooffproczerorows = mat->nooffproczerorows; 4980 B->nooffprocentries = mat->nooffprocentries; 4981 4982 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4983 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4984 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4985 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4986 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4987 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4988 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4989 PetscFunctionReturn(PETSC_SUCCESS); 4990 } 4991 4992 /*@ 4993 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4994 4995 Logically Collective 4996 4997 Input Parameter: 4998 . mat - the matrix 4999 5000 Output Parameter: 5001 . v - the diagonal of the matrix 5002 5003 Level: intermediate 5004 5005 Note: 5006 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5007 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5008 is larger than `ndiag`, the values of the remaining entries are unspecified. 5009 5010 Currently only correct in parallel for square matrices. 5011 5012 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5013 @*/ 5014 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5015 { 5016 PetscFunctionBegin; 5017 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5018 PetscValidType(mat, 1); 5019 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5020 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5021 MatCheckPreallocated(mat, 1); 5022 if (PetscDefined(USE_DEBUG)) { 5023 PetscInt nv, row, col, ndiag; 5024 5025 PetscCall(VecGetLocalSize(v, &nv)); 5026 PetscCall(MatGetLocalSize(mat, &row, &col)); 5027 ndiag = PetscMin(row, col); 5028 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); 5029 } 5030 5031 PetscUseTypeMethod(mat, getdiagonal, v); 5032 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5033 PetscFunctionReturn(PETSC_SUCCESS); 5034 } 5035 5036 /*@ 5037 MatGetRowMin - Gets the minimum value (of the real part) of each 5038 row of the matrix 5039 5040 Logically Collective 5041 5042 Input Parameter: 5043 . mat - the matrix 5044 5045 Output Parameters: 5046 + v - the vector for storing the maximums 5047 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5048 5049 Level: intermediate 5050 5051 Note: 5052 The result of this call are the same as if one converted the matrix to dense format 5053 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5054 5055 This code is only implemented for a couple of matrix formats. 5056 5057 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5058 `MatGetRowMax()` 5059 @*/ 5060 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5061 { 5062 PetscFunctionBegin; 5063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5064 PetscValidType(mat, 1); 5065 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5066 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5067 5068 if (!mat->cmap->N) { 5069 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5070 if (idx) { 5071 PetscInt i, m = mat->rmap->n; 5072 for (i = 0; i < m; i++) idx[i] = -1; 5073 } 5074 } else { 5075 MatCheckPreallocated(mat, 1); 5076 } 5077 PetscUseTypeMethod(mat, getrowmin, v, idx); 5078 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5079 PetscFunctionReturn(PETSC_SUCCESS); 5080 } 5081 5082 /*@ 5083 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5084 row of the matrix 5085 5086 Logically Collective 5087 5088 Input Parameter: 5089 . mat - the matrix 5090 5091 Output Parameters: 5092 + v - the vector for storing the minimums 5093 - idx - the indices of the column found for each row (or `NULL` if not needed) 5094 5095 Level: intermediate 5096 5097 Notes: 5098 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5099 row is 0 (the first column). 5100 5101 This code is only implemented for a couple of matrix formats. 5102 5103 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5104 @*/ 5105 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5106 { 5107 PetscFunctionBegin; 5108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5109 PetscValidType(mat, 1); 5110 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5112 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5113 5114 if (!mat->cmap->N) { 5115 PetscCall(VecSet(v, 0.0)); 5116 if (idx) { 5117 PetscInt i, m = mat->rmap->n; 5118 for (i = 0; i < m; i++) idx[i] = -1; 5119 } 5120 } else { 5121 MatCheckPreallocated(mat, 1); 5122 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5123 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5124 } 5125 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5126 PetscFunctionReturn(PETSC_SUCCESS); 5127 } 5128 5129 /*@ 5130 MatGetRowMax - Gets the maximum value (of the real part) of each 5131 row of the matrix 5132 5133 Logically Collective 5134 5135 Input Parameter: 5136 . mat - the matrix 5137 5138 Output Parameters: 5139 + v - the vector for storing the maximums 5140 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5141 5142 Level: intermediate 5143 5144 Notes: 5145 The result of this call are the same as if one converted the matrix to dense format 5146 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5147 5148 This code is only implemented for a couple of matrix formats. 5149 5150 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5151 @*/ 5152 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5153 { 5154 PetscFunctionBegin; 5155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5156 PetscValidType(mat, 1); 5157 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5158 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5159 5160 if (!mat->cmap->N) { 5161 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5162 if (idx) { 5163 PetscInt i, m = mat->rmap->n; 5164 for (i = 0; i < m; i++) idx[i] = -1; 5165 } 5166 } else { 5167 MatCheckPreallocated(mat, 1); 5168 PetscUseTypeMethod(mat, getrowmax, v, idx); 5169 } 5170 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5171 PetscFunctionReturn(PETSC_SUCCESS); 5172 } 5173 5174 /*@ 5175 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5176 row of the matrix 5177 5178 Logically Collective 5179 5180 Input Parameter: 5181 . mat - the matrix 5182 5183 Output Parameters: 5184 + v - the vector for storing the maximums 5185 - idx - the indices of the column found for each row (or `NULL` if not needed) 5186 5187 Level: intermediate 5188 5189 Notes: 5190 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5191 row is 0 (the first column). 5192 5193 This code is only implemented for a couple of matrix formats. 5194 5195 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5196 @*/ 5197 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5198 { 5199 PetscFunctionBegin; 5200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5201 PetscValidType(mat, 1); 5202 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5203 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5204 5205 if (!mat->cmap->N) { 5206 PetscCall(VecSet(v, 0.0)); 5207 if (idx) { 5208 PetscInt i, m = mat->rmap->n; 5209 for (i = 0; i < m; i++) idx[i] = -1; 5210 } 5211 } else { 5212 MatCheckPreallocated(mat, 1); 5213 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5214 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5215 } 5216 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5217 PetscFunctionReturn(PETSC_SUCCESS); 5218 } 5219 5220 /*@ 5221 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5222 5223 Logically Collective 5224 5225 Input Parameter: 5226 . mat - the matrix 5227 5228 Output Parameter: 5229 . v - the vector for storing the sum 5230 5231 Level: intermediate 5232 5233 This code is only implemented for a couple of matrix formats. 5234 5235 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5236 @*/ 5237 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5238 { 5239 PetscFunctionBegin; 5240 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5241 PetscValidType(mat, 1); 5242 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5244 5245 if (!mat->cmap->N) { 5246 PetscCall(VecSet(v, 0.0)); 5247 } else { 5248 MatCheckPreallocated(mat, 1); 5249 PetscUseTypeMethod(mat, getrowsumabs, v); 5250 } 5251 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5252 PetscFunctionReturn(PETSC_SUCCESS); 5253 } 5254 5255 /*@ 5256 MatGetRowSum - Gets the sum of each row of the matrix 5257 5258 Logically or Neighborhood Collective 5259 5260 Input Parameter: 5261 . mat - the matrix 5262 5263 Output Parameter: 5264 . v - the vector for storing the sum of rows 5265 5266 Level: intermediate 5267 5268 Note: 5269 This code is slow since it is not currently specialized for different formats 5270 5271 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5272 @*/ 5273 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5274 { 5275 Vec ones; 5276 5277 PetscFunctionBegin; 5278 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5279 PetscValidType(mat, 1); 5280 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5281 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5282 MatCheckPreallocated(mat, 1); 5283 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5284 PetscCall(VecSet(ones, 1.)); 5285 PetscCall(MatMult(mat, ones, v)); 5286 PetscCall(VecDestroy(&ones)); 5287 PetscFunctionReturn(PETSC_SUCCESS); 5288 } 5289 5290 /*@ 5291 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5292 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5293 5294 Collective 5295 5296 Input Parameter: 5297 . mat - the matrix to provide the transpose 5298 5299 Output Parameter: 5300 . 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 5301 5302 Level: advanced 5303 5304 Note: 5305 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 5306 routine allows bypassing that call. 5307 5308 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5309 @*/ 5310 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5311 { 5312 PetscContainer rB = NULL; 5313 MatParentState *rb = NULL; 5314 5315 PetscFunctionBegin; 5316 PetscCall(PetscNew(&rb)); 5317 rb->id = ((PetscObject)mat)->id; 5318 rb->state = 0; 5319 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5320 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5321 PetscCall(PetscContainerSetPointer(rB, rb)); 5322 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5323 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5324 PetscCall(PetscObjectDereference((PetscObject)rB)); 5325 PetscFunctionReturn(PETSC_SUCCESS); 5326 } 5327 5328 /*@ 5329 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5330 5331 Collective 5332 5333 Input Parameters: 5334 + mat - the matrix to transpose 5335 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5336 5337 Output Parameter: 5338 . B - the transpose 5339 5340 Level: intermediate 5341 5342 Notes: 5343 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5344 5345 `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 5346 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5347 5348 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. 5349 5350 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5351 5352 If mat is unchanged from the last call this function returns immediately without recomputing the result 5353 5354 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5355 5356 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5357 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5358 @*/ 5359 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5360 { 5361 PetscContainer rB = NULL; 5362 MatParentState *rb = NULL; 5363 5364 PetscFunctionBegin; 5365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5366 PetscValidType(mat, 1); 5367 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5368 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5369 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5370 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5371 MatCheckPreallocated(mat, 1); 5372 if (reuse == MAT_REUSE_MATRIX) { 5373 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5374 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5375 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5376 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5377 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5378 } 5379 5380 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5381 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5382 PetscUseTypeMethod(mat, transpose, reuse, B); 5383 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5384 } 5385 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5386 5387 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5388 if (reuse != MAT_INPLACE_MATRIX) { 5389 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5390 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5391 rb->state = ((PetscObject)mat)->state; 5392 rb->nonzerostate = mat->nonzerostate; 5393 } 5394 PetscFunctionReturn(PETSC_SUCCESS); 5395 } 5396 5397 /*@ 5398 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5399 5400 Collective 5401 5402 Input Parameter: 5403 . A - the matrix to transpose 5404 5405 Output Parameter: 5406 . 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 5407 numerical portion. 5408 5409 Level: intermediate 5410 5411 Note: 5412 This is not supported for many matrix types, use `MatTranspose()` in those cases 5413 5414 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5415 @*/ 5416 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5417 { 5418 PetscFunctionBegin; 5419 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5420 PetscValidType(A, 1); 5421 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5422 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5423 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5424 PetscUseTypeMethod(A, transposesymbolic, B); 5425 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5426 5427 PetscCall(MatTransposeSetPrecursor(A, *B)); 5428 PetscFunctionReturn(PETSC_SUCCESS); 5429 } 5430 5431 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5432 { 5433 PetscContainer rB; 5434 MatParentState *rb; 5435 5436 PetscFunctionBegin; 5437 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5438 PetscValidType(A, 1); 5439 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5440 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5441 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5442 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5443 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5444 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5445 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5446 PetscFunctionReturn(PETSC_SUCCESS); 5447 } 5448 5449 /*@ 5450 MatIsTranspose - Test whether a matrix is another one's transpose, 5451 or its own, in which case it tests symmetry. 5452 5453 Collective 5454 5455 Input Parameters: 5456 + A - the matrix to test 5457 . B - the matrix to test against, this can equal the first parameter 5458 - tol - tolerance, differences between entries smaller than this are counted as zero 5459 5460 Output Parameter: 5461 . flg - the result 5462 5463 Level: intermediate 5464 5465 Notes: 5466 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5467 test involves parallel copies of the block off-diagonal parts of the matrix. 5468 5469 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5470 @*/ 5471 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5472 { 5473 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5474 5475 PetscFunctionBegin; 5476 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5477 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5478 PetscAssertPointer(flg, 4); 5479 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5480 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5481 *flg = PETSC_FALSE; 5482 if (f && g) { 5483 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5484 PetscCall((*f)(A, B, tol, flg)); 5485 } else { 5486 MatType mattype; 5487 5488 PetscCall(MatGetType(f ? B : A, &mattype)); 5489 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5490 } 5491 PetscFunctionReturn(PETSC_SUCCESS); 5492 } 5493 5494 /*@ 5495 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5496 5497 Collective 5498 5499 Input Parameters: 5500 + mat - the matrix to transpose and complex conjugate 5501 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5502 5503 Output Parameter: 5504 . B - the Hermitian transpose 5505 5506 Level: intermediate 5507 5508 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5509 @*/ 5510 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5511 { 5512 PetscFunctionBegin; 5513 PetscCall(MatTranspose(mat, reuse, B)); 5514 #if defined(PETSC_USE_COMPLEX) 5515 PetscCall(MatConjugate(*B)); 5516 #endif 5517 PetscFunctionReturn(PETSC_SUCCESS); 5518 } 5519 5520 /*@ 5521 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5522 5523 Collective 5524 5525 Input Parameters: 5526 + A - the matrix to test 5527 . B - the matrix to test against, this can equal the first parameter 5528 - tol - tolerance, differences between entries smaller than this are counted as zero 5529 5530 Output Parameter: 5531 . flg - the result 5532 5533 Level: intermediate 5534 5535 Notes: 5536 Only available for `MATAIJ` matrices. 5537 5538 The sequential algorithm 5539 has a running time of the order of the number of nonzeros; the parallel 5540 test involves parallel copies of the block off-diagonal parts of the matrix. 5541 5542 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5543 @*/ 5544 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5545 { 5546 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5547 5548 PetscFunctionBegin; 5549 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5550 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5551 PetscAssertPointer(flg, 4); 5552 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5553 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5554 if (f && g) { 5555 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5556 PetscCall((*f)(A, B, tol, flg)); 5557 } 5558 PetscFunctionReturn(PETSC_SUCCESS); 5559 } 5560 5561 /*@ 5562 MatPermute - Creates a new matrix with rows and columns permuted from the 5563 original. 5564 5565 Collective 5566 5567 Input Parameters: 5568 + mat - the matrix to permute 5569 . row - row permutation, each processor supplies only the permutation for its rows 5570 - col - column permutation, each processor supplies only the permutation for its columns 5571 5572 Output Parameter: 5573 . B - the permuted matrix 5574 5575 Level: advanced 5576 5577 Note: 5578 The index sets map from row/col of permuted matrix to row/col of original matrix. 5579 The index sets should be on the same communicator as mat and have the same local sizes. 5580 5581 Developer Note: 5582 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5583 exploit the fact that row and col are permutations, consider implementing the 5584 more general `MatCreateSubMatrix()` instead. 5585 5586 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5587 @*/ 5588 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5589 { 5590 PetscFunctionBegin; 5591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5592 PetscValidType(mat, 1); 5593 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5594 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5595 PetscAssertPointer(B, 4); 5596 PetscCheckSameComm(mat, 1, row, 2); 5597 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5598 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5599 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5600 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5601 MatCheckPreallocated(mat, 1); 5602 5603 if (mat->ops->permute) { 5604 PetscUseTypeMethod(mat, permute, row, col, B); 5605 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5606 } else { 5607 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5608 } 5609 PetscFunctionReturn(PETSC_SUCCESS); 5610 } 5611 5612 /*@ 5613 MatEqual - Compares two matrices. 5614 5615 Collective 5616 5617 Input Parameters: 5618 + A - the first matrix 5619 - B - the second matrix 5620 5621 Output Parameter: 5622 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5623 5624 Level: intermediate 5625 5626 .seealso: [](ch_matrices), `Mat` 5627 @*/ 5628 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5629 { 5630 PetscFunctionBegin; 5631 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5632 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5633 PetscValidType(A, 1); 5634 PetscValidType(B, 2); 5635 PetscAssertPointer(flg, 3); 5636 PetscCheckSameComm(A, 1, B, 2); 5637 MatCheckPreallocated(A, 1); 5638 MatCheckPreallocated(B, 2); 5639 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5640 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5641 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, 5642 B->cmap->N); 5643 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5644 PetscUseTypeMethod(A, equal, B, flg); 5645 } else { 5646 PetscCall(MatMultEqual(A, B, 10, flg)); 5647 } 5648 PetscFunctionReturn(PETSC_SUCCESS); 5649 } 5650 5651 /*@ 5652 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5653 matrices that are stored as vectors. Either of the two scaling 5654 matrices can be `NULL`. 5655 5656 Collective 5657 5658 Input Parameters: 5659 + mat - the matrix to be scaled 5660 . l - the left scaling vector (or `NULL`) 5661 - r - the right scaling vector (or `NULL`) 5662 5663 Level: intermediate 5664 5665 Note: 5666 `MatDiagonalScale()` computes $A = LAR$, where 5667 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5668 The L scales the rows of the matrix, the R scales the columns of the matrix. 5669 5670 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5671 @*/ 5672 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5673 { 5674 PetscFunctionBegin; 5675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5676 PetscValidType(mat, 1); 5677 if (l) { 5678 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5679 PetscCheckSameComm(mat, 1, l, 2); 5680 } 5681 if (r) { 5682 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5683 PetscCheckSameComm(mat, 1, r, 3); 5684 } 5685 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5686 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5687 MatCheckPreallocated(mat, 1); 5688 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5689 5690 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5691 PetscUseTypeMethod(mat, diagonalscale, l, r); 5692 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5693 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5694 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5695 PetscFunctionReturn(PETSC_SUCCESS); 5696 } 5697 5698 /*@ 5699 MatScale - Scales all elements of a matrix by a given number. 5700 5701 Logically Collective 5702 5703 Input Parameters: 5704 + mat - the matrix to be scaled 5705 - a - the scaling value 5706 5707 Level: intermediate 5708 5709 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5710 @*/ 5711 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5712 { 5713 PetscFunctionBegin; 5714 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5715 PetscValidType(mat, 1); 5716 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5717 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5718 PetscValidLogicalCollectiveScalar(mat, a, 2); 5719 MatCheckPreallocated(mat, 1); 5720 5721 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5722 if (a != (PetscScalar)1.0) { 5723 PetscUseTypeMethod(mat, scale, a); 5724 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5725 } 5726 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5727 PetscFunctionReturn(PETSC_SUCCESS); 5728 } 5729 5730 /*@ 5731 MatNorm - Calculates various norms of a matrix. 5732 5733 Collective 5734 5735 Input Parameters: 5736 + mat - the matrix 5737 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5738 5739 Output Parameter: 5740 . nrm - the resulting norm 5741 5742 Level: intermediate 5743 5744 .seealso: [](ch_matrices), `Mat` 5745 @*/ 5746 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5747 { 5748 PetscFunctionBegin; 5749 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5750 PetscValidType(mat, 1); 5751 PetscAssertPointer(nrm, 3); 5752 5753 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5754 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5755 MatCheckPreallocated(mat, 1); 5756 5757 PetscUseTypeMethod(mat, norm, type, nrm); 5758 PetscFunctionReturn(PETSC_SUCCESS); 5759 } 5760 5761 /* 5762 This variable is used to prevent counting of MatAssemblyBegin() that 5763 are called from within a MatAssemblyEnd(). 5764 */ 5765 static PetscInt MatAssemblyEnd_InUse = 0; 5766 /*@ 5767 MatAssemblyBegin - Begins assembling the matrix. This routine should 5768 be called after completing all calls to `MatSetValues()`. 5769 5770 Collective 5771 5772 Input Parameters: 5773 + mat - the matrix 5774 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5775 5776 Level: beginner 5777 5778 Notes: 5779 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5780 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5781 5782 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5783 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5784 using the matrix. 5785 5786 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5787 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 5788 a global collective operation requiring all processes that share the matrix. 5789 5790 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5791 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5792 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5793 5794 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5795 @*/ 5796 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5797 { 5798 PetscFunctionBegin; 5799 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5800 PetscValidType(mat, 1); 5801 MatCheckPreallocated(mat, 1); 5802 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5803 if (mat->assembled) { 5804 mat->was_assembled = PETSC_TRUE; 5805 mat->assembled = PETSC_FALSE; 5806 } 5807 5808 if (!MatAssemblyEnd_InUse) { 5809 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5810 PetscTryTypeMethod(mat, assemblybegin, type); 5811 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5812 } else PetscTryTypeMethod(mat, assemblybegin, type); 5813 PetscFunctionReturn(PETSC_SUCCESS); 5814 } 5815 5816 /*@ 5817 MatAssembled - Indicates if a matrix has been assembled and is ready for 5818 use; for example, in matrix-vector product. 5819 5820 Not Collective 5821 5822 Input Parameter: 5823 . mat - the matrix 5824 5825 Output Parameter: 5826 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5827 5828 Level: advanced 5829 5830 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5831 @*/ 5832 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5833 { 5834 PetscFunctionBegin; 5835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5836 PetscAssertPointer(assembled, 2); 5837 *assembled = mat->assembled; 5838 PetscFunctionReturn(PETSC_SUCCESS); 5839 } 5840 5841 /*@ 5842 MatAssemblyEnd - Completes assembling the matrix. This routine should 5843 be called after `MatAssemblyBegin()`. 5844 5845 Collective 5846 5847 Input Parameters: 5848 + mat - the matrix 5849 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5850 5851 Options Database Keys: 5852 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5853 . -mat_view ::ascii_info_detail - Prints more detailed info 5854 . -mat_view - Prints matrix in ASCII format 5855 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5856 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5857 . -display <name> - Sets display name (default is host) 5858 . -draw_pause <sec> - Sets number of seconds to pause after display 5859 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5860 . -viewer_socket_machine <machine> - Machine to use for socket 5861 . -viewer_socket_port <port> - Port number to use for socket 5862 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5863 5864 Level: beginner 5865 5866 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5867 @*/ 5868 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5869 { 5870 static PetscInt inassm = 0; 5871 PetscBool flg = PETSC_FALSE; 5872 5873 PetscFunctionBegin; 5874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5875 PetscValidType(mat, 1); 5876 5877 inassm++; 5878 MatAssemblyEnd_InUse++; 5879 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5880 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5881 PetscTryTypeMethod(mat, assemblyend, type); 5882 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5883 } else PetscTryTypeMethod(mat, assemblyend, type); 5884 5885 /* Flush assembly is not a true assembly */ 5886 if (type != MAT_FLUSH_ASSEMBLY) { 5887 if (mat->num_ass) { 5888 if (!mat->symmetry_eternal) { 5889 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5890 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5891 } 5892 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5893 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5894 } 5895 mat->num_ass++; 5896 mat->assembled = PETSC_TRUE; 5897 mat->ass_nonzerostate = mat->nonzerostate; 5898 } 5899 5900 mat->insertmode = NOT_SET_VALUES; 5901 MatAssemblyEnd_InUse--; 5902 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5903 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5904 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5905 5906 if (mat->checksymmetryonassembly) { 5907 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5908 if (flg) { 5909 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5910 } else { 5911 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5912 } 5913 } 5914 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5915 } 5916 inassm--; 5917 PetscFunctionReturn(PETSC_SUCCESS); 5918 } 5919 5920 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5921 /*@ 5922 MatSetOption - Sets a parameter option for a matrix. Some options 5923 may be specific to certain storage formats. Some options 5924 determine how values will be inserted (or added). Sorted, 5925 row-oriented input will generally assemble the fastest. The default 5926 is row-oriented. 5927 5928 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5929 5930 Input Parameters: 5931 + mat - the matrix 5932 . op - the option, one of those listed below (and possibly others), 5933 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5934 5935 Options Describing Matrix Structure: 5936 + `MAT_SPD` - symmetric positive definite 5937 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5938 . `MAT_HERMITIAN` - transpose is the complex conjugation 5939 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5940 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5941 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5942 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5943 5944 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5945 do not need to be computed (usually at a high cost) 5946 5947 Options For Use with `MatSetValues()`: 5948 Insert a logically dense subblock, which can be 5949 . `MAT_ROW_ORIENTED` - row-oriented (default) 5950 5951 These options reflect the data you pass in with `MatSetValues()`; it has 5952 nothing to do with how the data is stored internally in the matrix 5953 data structure. 5954 5955 When (re)assembling a matrix, we can restrict the input for 5956 efficiency/debugging purposes. These options include 5957 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5958 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5959 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5960 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5961 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5962 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5963 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5964 performance for very large process counts. 5965 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5966 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5967 functions, instead sending only neighbor messages. 5968 5969 Level: intermediate 5970 5971 Notes: 5972 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5973 5974 Some options are relevant only for particular matrix types and 5975 are thus ignored by others. Other options are not supported by 5976 certain matrix types and will generate an error message if set. 5977 5978 If using Fortran to compute a matrix, one may need to 5979 use the column-oriented option (or convert to the row-oriented 5980 format). 5981 5982 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5983 that would generate a new entry in the nonzero structure is instead 5984 ignored. Thus, if memory has not already been allocated for this particular 5985 data, then the insertion is ignored. For dense matrices, in which 5986 the entire array is allocated, no entries are ever ignored. 5987 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5988 5989 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5990 that would generate a new entry in the nonzero structure instead produces 5991 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 5992 5993 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5994 that would generate a new entry that has not been preallocated will 5995 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5996 only.) This is a useful flag when debugging matrix memory preallocation. 5997 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5998 5999 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6000 other processors should be dropped, rather than stashed. 6001 This is useful if you know that the "owning" processor is also 6002 always generating the correct matrix entries, so that PETSc need 6003 not transfer duplicate entries generated on another processor. 6004 6005 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6006 searches during matrix assembly. When this flag is set, the hash table 6007 is created during the first matrix assembly. This hash table is 6008 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6009 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6010 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6011 supported by `MATMPIBAIJ` format only. 6012 6013 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6014 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6015 6016 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6017 a zero location in the matrix 6018 6019 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6020 6021 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6022 zero row routines and thus improves performance for very large process counts. 6023 6024 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6025 part of the matrix (since they should match the upper triangular part). 6026 6027 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6028 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6029 with finite difference schemes with non-periodic boundary conditions. 6030 6031 Developer Note: 6032 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6033 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6034 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6035 not changed. 6036 6037 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6038 @*/ 6039 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6040 { 6041 PetscFunctionBegin; 6042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6043 if (op > 0) { 6044 PetscValidLogicalCollectiveEnum(mat, op, 2); 6045 PetscValidLogicalCollectiveBool(mat, flg, 3); 6046 } 6047 6048 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); 6049 6050 switch (op) { 6051 case MAT_FORCE_DIAGONAL_ENTRIES: 6052 mat->force_diagonals = flg; 6053 PetscFunctionReturn(PETSC_SUCCESS); 6054 case MAT_NO_OFF_PROC_ENTRIES: 6055 mat->nooffprocentries = flg; 6056 PetscFunctionReturn(PETSC_SUCCESS); 6057 case MAT_SUBSET_OFF_PROC_ENTRIES: 6058 mat->assembly_subset = flg; 6059 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6060 #if !defined(PETSC_HAVE_MPIUNI) 6061 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6062 #endif 6063 mat->stash.first_assembly_done = PETSC_FALSE; 6064 } 6065 PetscFunctionReturn(PETSC_SUCCESS); 6066 case MAT_NO_OFF_PROC_ZERO_ROWS: 6067 mat->nooffproczerorows = flg; 6068 PetscFunctionReturn(PETSC_SUCCESS); 6069 case MAT_SPD: 6070 if (flg) { 6071 mat->spd = PETSC_BOOL3_TRUE; 6072 mat->symmetric = PETSC_BOOL3_TRUE; 6073 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6074 } else { 6075 mat->spd = PETSC_BOOL3_FALSE; 6076 } 6077 break; 6078 case MAT_SYMMETRIC: 6079 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6080 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6081 #if !defined(PETSC_USE_COMPLEX) 6082 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6083 #endif 6084 break; 6085 case MAT_HERMITIAN: 6086 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6087 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6088 #if !defined(PETSC_USE_COMPLEX) 6089 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6090 #endif 6091 break; 6092 case MAT_STRUCTURALLY_SYMMETRIC: 6093 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6094 break; 6095 case MAT_SYMMETRY_ETERNAL: 6096 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"); 6097 mat->symmetry_eternal = flg; 6098 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6099 break; 6100 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6101 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"); 6102 mat->structural_symmetry_eternal = flg; 6103 break; 6104 case MAT_SPD_ETERNAL: 6105 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"); 6106 mat->spd_eternal = flg; 6107 if (flg) { 6108 mat->structural_symmetry_eternal = PETSC_TRUE; 6109 mat->symmetry_eternal = PETSC_TRUE; 6110 } 6111 break; 6112 case MAT_STRUCTURE_ONLY: 6113 mat->structure_only = flg; 6114 break; 6115 case MAT_SORTED_FULL: 6116 mat->sortedfull = flg; 6117 break; 6118 default: 6119 break; 6120 } 6121 PetscTryTypeMethod(mat, setoption, op, flg); 6122 PetscFunctionReturn(PETSC_SUCCESS); 6123 } 6124 6125 /*@ 6126 MatGetOption - Gets a parameter option that has been set for a matrix. 6127 6128 Logically Collective 6129 6130 Input Parameters: 6131 + mat - the matrix 6132 - op - the option, this only responds to certain options, check the code for which ones 6133 6134 Output Parameter: 6135 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6136 6137 Level: intermediate 6138 6139 Notes: 6140 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6141 6142 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6143 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6144 6145 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6146 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6147 @*/ 6148 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6149 { 6150 PetscFunctionBegin; 6151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6152 PetscValidType(mat, 1); 6153 6154 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); 6155 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()"); 6156 6157 switch (op) { 6158 case MAT_NO_OFF_PROC_ENTRIES: 6159 *flg = mat->nooffprocentries; 6160 break; 6161 case MAT_NO_OFF_PROC_ZERO_ROWS: 6162 *flg = mat->nooffproczerorows; 6163 break; 6164 case MAT_SYMMETRIC: 6165 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6166 break; 6167 case MAT_HERMITIAN: 6168 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6169 break; 6170 case MAT_STRUCTURALLY_SYMMETRIC: 6171 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6172 break; 6173 case MAT_SPD: 6174 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6175 break; 6176 case MAT_SYMMETRY_ETERNAL: 6177 *flg = mat->symmetry_eternal; 6178 break; 6179 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6180 *flg = mat->symmetry_eternal; 6181 break; 6182 default: 6183 break; 6184 } 6185 PetscFunctionReturn(PETSC_SUCCESS); 6186 } 6187 6188 /*@ 6189 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6190 this routine retains the old nonzero structure. 6191 6192 Logically Collective 6193 6194 Input Parameter: 6195 . mat - the matrix 6196 6197 Level: intermediate 6198 6199 Note: 6200 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. 6201 See the Performance chapter of the users manual for information on preallocating matrices. 6202 6203 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6204 @*/ 6205 PetscErrorCode MatZeroEntries(Mat mat) 6206 { 6207 PetscFunctionBegin; 6208 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6209 PetscValidType(mat, 1); 6210 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6211 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"); 6212 MatCheckPreallocated(mat, 1); 6213 6214 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6215 PetscUseTypeMethod(mat, zeroentries); 6216 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6217 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6218 PetscFunctionReturn(PETSC_SUCCESS); 6219 } 6220 6221 /*@ 6222 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6223 of a set of rows and columns of a matrix. 6224 6225 Collective 6226 6227 Input Parameters: 6228 + mat - the matrix 6229 . numRows - the number of rows/columns to zero 6230 . rows - the global row indices 6231 . diag - value put in the diagonal of the eliminated rows 6232 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6233 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6234 6235 Level: intermediate 6236 6237 Notes: 6238 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6239 6240 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6241 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 6242 6243 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6244 Krylov method to take advantage of the known solution on the zeroed rows. 6245 6246 For the parallel case, all processes that share the matrix (i.e., 6247 those in the communicator used for matrix creation) MUST call this 6248 routine, regardless of whether any rows being zeroed are owned by 6249 them. 6250 6251 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6252 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 6253 missing. 6254 6255 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6256 list only rows local to itself). 6257 6258 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6259 6260 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6261 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6262 @*/ 6263 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6264 { 6265 PetscFunctionBegin; 6266 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6267 PetscValidType(mat, 1); 6268 if (numRows) PetscAssertPointer(rows, 3); 6269 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6270 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6271 MatCheckPreallocated(mat, 1); 6272 6273 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6274 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6275 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6276 PetscFunctionReturn(PETSC_SUCCESS); 6277 } 6278 6279 /*@ 6280 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6281 of a set of rows and columns of a matrix. 6282 6283 Collective 6284 6285 Input Parameters: 6286 + mat - the matrix 6287 . is - the rows to zero 6288 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6289 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6290 - b - optional vector of right-hand side, that will be adjusted by provided solution 6291 6292 Level: intermediate 6293 6294 Note: 6295 See `MatZeroRowsColumns()` for details on how this routine operates. 6296 6297 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6298 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6299 @*/ 6300 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6301 { 6302 PetscInt numRows; 6303 const PetscInt *rows; 6304 6305 PetscFunctionBegin; 6306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6307 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6308 PetscValidType(mat, 1); 6309 PetscValidType(is, 2); 6310 PetscCall(ISGetLocalSize(is, &numRows)); 6311 PetscCall(ISGetIndices(is, &rows)); 6312 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6313 PetscCall(ISRestoreIndices(is, &rows)); 6314 PetscFunctionReturn(PETSC_SUCCESS); 6315 } 6316 6317 /*@ 6318 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6319 of a set of rows of a matrix. 6320 6321 Collective 6322 6323 Input Parameters: 6324 + mat - the matrix 6325 . numRows - the number of rows to zero 6326 . rows - the global row indices 6327 . diag - value put in the diagonal of the zeroed rows 6328 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6329 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6330 6331 Level: intermediate 6332 6333 Notes: 6334 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6335 6336 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6337 6338 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6339 Krylov method to take advantage of the known solution on the zeroed rows. 6340 6341 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) 6342 from the matrix. 6343 6344 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6345 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 6346 formats this does not alter the nonzero structure. 6347 6348 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6349 of the matrix is not changed the values are 6350 merely zeroed. 6351 6352 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6353 formats can optionally remove the main diagonal entry from the 6354 nonzero structure as well, by passing 0.0 as the final argument). 6355 6356 For the parallel case, all processes that share the matrix (i.e., 6357 those in the communicator used for matrix creation) MUST call this 6358 routine, regardless of whether any rows being zeroed are owned by 6359 them. 6360 6361 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6362 list only rows local to itself). 6363 6364 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6365 owns that are to be zeroed. This saves a global synchronization in the implementation. 6366 6367 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6368 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6369 @*/ 6370 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6371 { 6372 PetscFunctionBegin; 6373 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6374 PetscValidType(mat, 1); 6375 if (numRows) PetscAssertPointer(rows, 3); 6376 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6377 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6378 MatCheckPreallocated(mat, 1); 6379 6380 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6381 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6382 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6383 PetscFunctionReturn(PETSC_SUCCESS); 6384 } 6385 6386 /*@ 6387 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6388 of a set of rows of a matrix. 6389 6390 Collective 6391 6392 Input Parameters: 6393 + mat - the matrix 6394 . is - index set of rows to remove (if `NULL` then no row is removed) 6395 . diag - value put in all diagonals of eliminated rows 6396 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6397 - b - optional vector of right-hand side, that will be adjusted by provided solution 6398 6399 Level: intermediate 6400 6401 Note: 6402 See `MatZeroRows()` for details on how this routine operates. 6403 6404 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6405 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6406 @*/ 6407 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6408 { 6409 PetscInt numRows = 0; 6410 const PetscInt *rows = NULL; 6411 6412 PetscFunctionBegin; 6413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6414 PetscValidType(mat, 1); 6415 if (is) { 6416 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6417 PetscCall(ISGetLocalSize(is, &numRows)); 6418 PetscCall(ISGetIndices(is, &rows)); 6419 } 6420 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6421 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6422 PetscFunctionReturn(PETSC_SUCCESS); 6423 } 6424 6425 /*@ 6426 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6427 of a set of rows of a matrix. These rows must be local to the process. 6428 6429 Collective 6430 6431 Input Parameters: 6432 + mat - the matrix 6433 . numRows - the number of rows to remove 6434 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6435 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6436 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6437 - b - optional vector of right-hand side, that will be adjusted by provided solution 6438 6439 Level: intermediate 6440 6441 Notes: 6442 See `MatZeroRows()` for details on how this routine operates. 6443 6444 The grid coordinates are across the entire grid, not just the local portion 6445 6446 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6447 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6448 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6449 `DM_BOUNDARY_PERIODIC` boundary type. 6450 6451 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 6452 a single value per point) you can skip filling those indices. 6453 6454 Fortran Note: 6455 `idxm` and `idxn` should be declared as 6456 $ MatStencil idxm(4, m) 6457 and the values inserted using 6458 .vb 6459 idxm(MatStencil_i, 1) = i 6460 idxm(MatStencil_j, 1) = j 6461 idxm(MatStencil_k, 1) = k 6462 idxm(MatStencil_c, 1) = c 6463 etc 6464 .ve 6465 6466 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6467 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6468 @*/ 6469 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6470 { 6471 PetscInt dim = mat->stencil.dim; 6472 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6473 PetscInt *dims = mat->stencil.dims + 1; 6474 PetscInt *starts = mat->stencil.starts; 6475 PetscInt *dxm = (PetscInt *)rows; 6476 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6477 6478 PetscFunctionBegin; 6479 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6480 PetscValidType(mat, 1); 6481 if (numRows) PetscAssertPointer(rows, 3); 6482 6483 PetscCall(PetscMalloc1(numRows, &jdxm)); 6484 for (i = 0; i < numRows; ++i) { 6485 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6486 for (j = 0; j < 3 - sdim; ++j) dxm++; 6487 /* Local index in X dir */ 6488 tmp = *dxm++ - starts[0]; 6489 /* Loop over remaining dimensions */ 6490 for (j = 0; j < dim - 1; ++j) { 6491 /* If nonlocal, set index to be negative */ 6492 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6493 /* Update local index */ 6494 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6495 } 6496 /* Skip component slot if necessary */ 6497 if (mat->stencil.noc) dxm++; 6498 /* Local row number */ 6499 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6500 } 6501 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6502 PetscCall(PetscFree(jdxm)); 6503 PetscFunctionReturn(PETSC_SUCCESS); 6504 } 6505 6506 /*@ 6507 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6508 of a set of rows and columns of a matrix. 6509 6510 Collective 6511 6512 Input Parameters: 6513 + mat - the matrix 6514 . numRows - the number of rows/columns to remove 6515 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6516 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6517 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6518 - b - optional vector of right-hand side, that will be adjusted by provided solution 6519 6520 Level: intermediate 6521 6522 Notes: 6523 See `MatZeroRowsColumns()` for details on how this routine operates. 6524 6525 The grid coordinates are across the entire grid, not just the local portion 6526 6527 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6528 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6529 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6530 `DM_BOUNDARY_PERIODIC` boundary type. 6531 6532 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 6533 a single value per point) you can skip filling those indices. 6534 6535 Fortran Note: 6536 `idxm` and `idxn` should be declared as 6537 $ MatStencil idxm(4, m) 6538 and the values inserted using 6539 .vb 6540 idxm(MatStencil_i, 1) = i 6541 idxm(MatStencil_j, 1) = j 6542 idxm(MatStencil_k, 1) = k 6543 idxm(MatStencil_c, 1) = c 6544 etc 6545 .ve 6546 6547 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6548 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6549 @*/ 6550 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6551 { 6552 PetscInt dim = mat->stencil.dim; 6553 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6554 PetscInt *dims = mat->stencil.dims + 1; 6555 PetscInt *starts = mat->stencil.starts; 6556 PetscInt *dxm = (PetscInt *)rows; 6557 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6558 6559 PetscFunctionBegin; 6560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6561 PetscValidType(mat, 1); 6562 if (numRows) PetscAssertPointer(rows, 3); 6563 6564 PetscCall(PetscMalloc1(numRows, &jdxm)); 6565 for (i = 0; i < numRows; ++i) { 6566 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6567 for (j = 0; j < 3 - sdim; ++j) dxm++; 6568 /* Local index in X dir */ 6569 tmp = *dxm++ - starts[0]; 6570 /* Loop over remaining dimensions */ 6571 for (j = 0; j < dim - 1; ++j) { 6572 /* If nonlocal, set index to be negative */ 6573 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6574 /* Update local index */ 6575 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6576 } 6577 /* Skip component slot if necessary */ 6578 if (mat->stencil.noc) dxm++; 6579 /* Local row number */ 6580 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6581 } 6582 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6583 PetscCall(PetscFree(jdxm)); 6584 PetscFunctionReturn(PETSC_SUCCESS); 6585 } 6586 6587 /*@ 6588 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6589 of a set of rows of a matrix; using local numbering of rows. 6590 6591 Collective 6592 6593 Input Parameters: 6594 + mat - the matrix 6595 . numRows - the number of rows to remove 6596 . rows - the local row indices 6597 . diag - value put in all diagonals of eliminated rows 6598 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6599 - b - optional vector of right-hand side, that will be adjusted by provided solution 6600 6601 Level: intermediate 6602 6603 Notes: 6604 Before calling `MatZeroRowsLocal()`, the user must first set the 6605 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6606 6607 See `MatZeroRows()` for details on how this routine operates. 6608 6609 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6610 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6611 @*/ 6612 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6613 { 6614 PetscFunctionBegin; 6615 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6616 PetscValidType(mat, 1); 6617 if (numRows) PetscAssertPointer(rows, 3); 6618 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6619 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6620 MatCheckPreallocated(mat, 1); 6621 6622 if (mat->ops->zerorowslocal) { 6623 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6624 } else { 6625 IS is, newis; 6626 const PetscInt *newRows; 6627 6628 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6629 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6630 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6631 PetscCall(ISGetIndices(newis, &newRows)); 6632 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6633 PetscCall(ISRestoreIndices(newis, &newRows)); 6634 PetscCall(ISDestroy(&newis)); 6635 PetscCall(ISDestroy(&is)); 6636 } 6637 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6638 PetscFunctionReturn(PETSC_SUCCESS); 6639 } 6640 6641 /*@ 6642 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6643 of a set of rows of a matrix; using local numbering of rows. 6644 6645 Collective 6646 6647 Input Parameters: 6648 + mat - the matrix 6649 . is - index set of rows to remove 6650 . diag - value put in all diagonals of eliminated rows 6651 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6652 - b - optional vector of right-hand side, that will be adjusted by provided solution 6653 6654 Level: intermediate 6655 6656 Notes: 6657 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6658 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6659 6660 See `MatZeroRows()` for details on how this routine operates. 6661 6662 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6663 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6664 @*/ 6665 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6666 { 6667 PetscInt numRows; 6668 const PetscInt *rows; 6669 6670 PetscFunctionBegin; 6671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6672 PetscValidType(mat, 1); 6673 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6674 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6675 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6676 MatCheckPreallocated(mat, 1); 6677 6678 PetscCall(ISGetLocalSize(is, &numRows)); 6679 PetscCall(ISGetIndices(is, &rows)); 6680 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6681 PetscCall(ISRestoreIndices(is, &rows)); 6682 PetscFunctionReturn(PETSC_SUCCESS); 6683 } 6684 6685 /*@ 6686 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6687 of a set of rows and columns of a matrix; using local numbering of rows. 6688 6689 Collective 6690 6691 Input Parameters: 6692 + mat - the matrix 6693 . numRows - the number of rows to remove 6694 . rows - the global row indices 6695 . diag - value put in all diagonals of eliminated rows 6696 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6697 - b - optional vector of right-hand side, that will be adjusted by provided solution 6698 6699 Level: intermediate 6700 6701 Notes: 6702 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6703 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6704 6705 See `MatZeroRowsColumns()` for details on how this routine operates. 6706 6707 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6708 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6709 @*/ 6710 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6711 { 6712 IS is, newis; 6713 const PetscInt *newRows; 6714 6715 PetscFunctionBegin; 6716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6717 PetscValidType(mat, 1); 6718 if (numRows) PetscAssertPointer(rows, 3); 6719 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6720 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6721 MatCheckPreallocated(mat, 1); 6722 6723 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6724 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6725 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6726 PetscCall(ISGetIndices(newis, &newRows)); 6727 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6728 PetscCall(ISRestoreIndices(newis, &newRows)); 6729 PetscCall(ISDestroy(&newis)); 6730 PetscCall(ISDestroy(&is)); 6731 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6732 PetscFunctionReturn(PETSC_SUCCESS); 6733 } 6734 6735 /*@ 6736 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6737 of a set of rows and columns of a matrix; using local numbering of rows. 6738 6739 Collective 6740 6741 Input Parameters: 6742 + mat - the matrix 6743 . is - index set of rows to remove 6744 . diag - value put in all diagonals of eliminated rows 6745 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6746 - b - optional vector of right-hand side, that will be adjusted by provided solution 6747 6748 Level: intermediate 6749 6750 Notes: 6751 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6752 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6753 6754 See `MatZeroRowsColumns()` for details on how this routine operates. 6755 6756 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6757 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6758 @*/ 6759 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6760 { 6761 PetscInt numRows; 6762 const PetscInt *rows; 6763 6764 PetscFunctionBegin; 6765 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6766 PetscValidType(mat, 1); 6767 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6768 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6769 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6770 MatCheckPreallocated(mat, 1); 6771 6772 PetscCall(ISGetLocalSize(is, &numRows)); 6773 PetscCall(ISGetIndices(is, &rows)); 6774 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6775 PetscCall(ISRestoreIndices(is, &rows)); 6776 PetscFunctionReturn(PETSC_SUCCESS); 6777 } 6778 6779 /*@ 6780 MatGetSize - Returns the numbers of rows and columns in a matrix. 6781 6782 Not Collective 6783 6784 Input Parameter: 6785 . mat - the matrix 6786 6787 Output Parameters: 6788 + m - the number of global rows 6789 - n - the number of global columns 6790 6791 Level: beginner 6792 6793 Note: 6794 Both output parameters can be `NULL` on input. 6795 6796 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6797 @*/ 6798 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6799 { 6800 PetscFunctionBegin; 6801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6802 if (m) *m = mat->rmap->N; 6803 if (n) *n = mat->cmap->N; 6804 PetscFunctionReturn(PETSC_SUCCESS); 6805 } 6806 6807 /*@ 6808 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6809 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6810 6811 Not Collective 6812 6813 Input Parameter: 6814 . mat - the matrix 6815 6816 Output Parameters: 6817 + m - the number of local rows, use `NULL` to not obtain this value 6818 - n - the number of local columns, use `NULL` to not obtain this value 6819 6820 Level: beginner 6821 6822 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6823 @*/ 6824 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6825 { 6826 PetscFunctionBegin; 6827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6828 if (m) PetscAssertPointer(m, 2); 6829 if (n) PetscAssertPointer(n, 3); 6830 if (m) *m = mat->rmap->n; 6831 if (n) *n = mat->cmap->n; 6832 PetscFunctionReturn(PETSC_SUCCESS); 6833 } 6834 6835 /*@ 6836 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6837 vector one multiplies this matrix by that are owned by this processor. 6838 6839 Not Collective, unless matrix has not been allocated, then collective 6840 6841 Input Parameter: 6842 . mat - the matrix 6843 6844 Output Parameters: 6845 + m - the global index of the first local column, use `NULL` to not obtain this value 6846 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6847 6848 Level: developer 6849 6850 Notes: 6851 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6852 6853 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6854 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6855 6856 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6857 the local values in the matrix. 6858 6859 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6860 Layouts](sec_matlayout) for details on matrix layouts. 6861 6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6863 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6864 @*/ 6865 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6866 { 6867 PetscFunctionBegin; 6868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6869 PetscValidType(mat, 1); 6870 if (m) PetscAssertPointer(m, 2); 6871 if (n) PetscAssertPointer(n, 3); 6872 MatCheckPreallocated(mat, 1); 6873 if (m) *m = mat->cmap->rstart; 6874 if (n) *n = mat->cmap->rend; 6875 PetscFunctionReturn(PETSC_SUCCESS); 6876 } 6877 6878 /*@ 6879 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6880 this MPI process. 6881 6882 Not Collective 6883 6884 Input Parameter: 6885 . mat - the matrix 6886 6887 Output Parameters: 6888 + m - the global index of the first local row, use `NULL` to not obtain this value 6889 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6890 6891 Level: beginner 6892 6893 Notes: 6894 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6895 6896 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6897 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6898 6899 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6900 the local values in the matrix. 6901 6902 The high argument is one more than the last element stored locally. 6903 6904 For all matrices it returns the range of matrix rows associated with rows of a vector that 6905 would contain the result of a matrix vector product with this matrix. See [Matrix 6906 Layouts](sec_matlayout) for details on matrix layouts. 6907 6908 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6909 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6910 @*/ 6911 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6912 { 6913 PetscFunctionBegin; 6914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6915 PetscValidType(mat, 1); 6916 if (m) PetscAssertPointer(m, 2); 6917 if (n) PetscAssertPointer(n, 3); 6918 MatCheckPreallocated(mat, 1); 6919 if (m) *m = mat->rmap->rstart; 6920 if (n) *n = mat->rmap->rend; 6921 PetscFunctionReturn(PETSC_SUCCESS); 6922 } 6923 6924 /*@C 6925 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6926 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6927 6928 Not Collective, unless matrix has not been allocated 6929 6930 Input Parameter: 6931 . mat - the matrix 6932 6933 Output Parameter: 6934 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6935 where `size` is the number of MPI processes used by `mat` 6936 6937 Level: beginner 6938 6939 Notes: 6940 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6941 6942 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6943 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6944 6945 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6946 the local values in the matrix. 6947 6948 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6949 would contain the result of a matrix vector product with this matrix. See [Matrix 6950 Layouts](sec_matlayout) for details on matrix layouts. 6951 6952 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6953 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6954 `DMDAGetGhostCorners()`, `DM` 6955 @*/ 6956 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6957 { 6958 PetscFunctionBegin; 6959 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6960 PetscValidType(mat, 1); 6961 MatCheckPreallocated(mat, 1); 6962 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6963 PetscFunctionReturn(PETSC_SUCCESS); 6964 } 6965 6966 /*@C 6967 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6968 vector one multiplies this vector by that are owned by each processor. 6969 6970 Not Collective, unless matrix has not been allocated 6971 6972 Input Parameter: 6973 . mat - the matrix 6974 6975 Output Parameter: 6976 . ranges - start of each processors portion plus one more than the total length at the end 6977 6978 Level: beginner 6979 6980 Notes: 6981 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6982 6983 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6984 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6985 6986 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6987 the local values in the matrix. 6988 6989 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6990 Layouts](sec_matlayout) for details on matrix layouts. 6991 6992 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6993 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6994 `DMDAGetGhostCorners()`, `DM` 6995 @*/ 6996 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6997 { 6998 PetscFunctionBegin; 6999 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7000 PetscValidType(mat, 1); 7001 MatCheckPreallocated(mat, 1); 7002 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7003 PetscFunctionReturn(PETSC_SUCCESS); 7004 } 7005 7006 /*@ 7007 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7008 7009 Not Collective 7010 7011 Input Parameter: 7012 . A - matrix 7013 7014 Output Parameters: 7015 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7016 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7017 7018 Level: intermediate 7019 7020 Note: 7021 You should call `ISDestroy()` on the returned `IS` 7022 7023 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7024 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7025 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7026 details on matrix layouts. 7027 7028 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7029 @*/ 7030 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7031 { 7032 PetscErrorCode (*f)(Mat, IS *, IS *); 7033 7034 PetscFunctionBegin; 7035 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7036 PetscValidType(A, 1); 7037 MatCheckPreallocated(A, 1); 7038 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7039 if (f) { 7040 PetscCall((*f)(A, rows, cols)); 7041 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7042 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7043 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7044 } 7045 PetscFunctionReturn(PETSC_SUCCESS); 7046 } 7047 7048 /*@ 7049 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7050 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7051 to complete the factorization. 7052 7053 Collective 7054 7055 Input Parameters: 7056 + fact - the factorized matrix obtained with `MatGetFactor()` 7057 . mat - the matrix 7058 . row - row permutation 7059 . col - column permutation 7060 - info - structure containing 7061 .vb 7062 levels - number of levels of fill. 7063 expected fill - as ratio of original fill. 7064 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7065 missing diagonal entries) 7066 .ve 7067 7068 Level: developer 7069 7070 Notes: 7071 See [Matrix Factorization](sec_matfactor) for additional information. 7072 7073 Most users should employ the `KSP` interface for linear solvers 7074 instead of working directly with matrix algebra routines such as this. 7075 See, e.g., `KSPCreate()`. 7076 7077 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7078 7079 Developer Note: 7080 The Fortran interface is not autogenerated as the 7081 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7082 7083 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7084 `MatGetOrdering()`, `MatFactorInfo` 7085 @*/ 7086 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7087 { 7088 PetscFunctionBegin; 7089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7090 PetscValidType(mat, 2); 7091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7092 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7093 PetscAssertPointer(info, 5); 7094 PetscAssertPointer(fact, 1); 7095 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7096 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7097 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7098 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7099 MatCheckPreallocated(mat, 2); 7100 7101 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7102 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7103 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7104 PetscFunctionReturn(PETSC_SUCCESS); 7105 } 7106 7107 /*@ 7108 MatICCFactorSymbolic - Performs symbolic incomplete 7109 Cholesky factorization for a symmetric matrix. Use 7110 `MatCholeskyFactorNumeric()` to complete the factorization. 7111 7112 Collective 7113 7114 Input Parameters: 7115 + fact - the factorized matrix obtained with `MatGetFactor()` 7116 . mat - the matrix to be factored 7117 . perm - row and column permutation 7118 - info - structure containing 7119 .vb 7120 levels - number of levels of fill. 7121 expected fill - as ratio of original fill. 7122 .ve 7123 7124 Level: developer 7125 7126 Notes: 7127 Most users should employ the `KSP` interface for linear solvers 7128 instead of working directly with matrix algebra routines such as this. 7129 See, e.g., `KSPCreate()`. 7130 7131 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7132 7133 Developer Note: 7134 The Fortran interface is not autogenerated as the 7135 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7136 7137 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7138 @*/ 7139 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7140 { 7141 PetscFunctionBegin; 7142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7143 PetscValidType(mat, 2); 7144 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7145 PetscAssertPointer(info, 4); 7146 PetscAssertPointer(fact, 1); 7147 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7148 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7149 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7150 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7151 MatCheckPreallocated(mat, 2); 7152 7153 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7154 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7155 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7156 PetscFunctionReturn(PETSC_SUCCESS); 7157 } 7158 7159 /*@C 7160 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7161 points to an array of valid matrices, they may be reused to store the new 7162 submatrices. 7163 7164 Collective 7165 7166 Input Parameters: 7167 + mat - the matrix 7168 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7169 . irow - index set of rows to extract 7170 . icol - index set of columns to extract 7171 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7172 7173 Output Parameter: 7174 . submat - the array of submatrices 7175 7176 Level: advanced 7177 7178 Notes: 7179 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7180 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7181 to extract a parallel submatrix. 7182 7183 Some matrix types place restrictions on the row and column 7184 indices, such as that they be sorted or that they be equal to each other. 7185 7186 The index sets may not have duplicate entries. 7187 7188 When extracting submatrices from a parallel matrix, each processor can 7189 form a different submatrix by setting the rows and columns of its 7190 individual index sets according to the local submatrix desired. 7191 7192 When finished using the submatrices, the user should destroy 7193 them with `MatDestroySubMatrices()`. 7194 7195 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7196 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7197 7198 This routine creates the matrices in submat; you should NOT create them before 7199 calling it. It also allocates the array of matrix pointers submat. 7200 7201 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7202 request one row/column in a block, they must request all rows/columns that are in 7203 that block. For example, if the block size is 2 you cannot request just row 0 and 7204 column 0. 7205 7206 Fortran Note: 7207 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7208 7209 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7210 @*/ 7211 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7212 { 7213 PetscInt i; 7214 PetscBool eq; 7215 7216 PetscFunctionBegin; 7217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7218 PetscValidType(mat, 1); 7219 if (n) { 7220 PetscAssertPointer(irow, 3); 7221 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7222 PetscAssertPointer(icol, 4); 7223 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7224 } 7225 PetscAssertPointer(submat, 6); 7226 if (n && scall == MAT_REUSE_MATRIX) { 7227 PetscAssertPointer(*submat, 6); 7228 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7229 } 7230 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7231 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7232 MatCheckPreallocated(mat, 1); 7233 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7234 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7235 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7236 for (i = 0; i < n; i++) { 7237 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7238 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7239 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7240 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7241 if (mat->boundtocpu && mat->bindingpropagates) { 7242 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7243 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7244 } 7245 #endif 7246 } 7247 PetscFunctionReturn(PETSC_SUCCESS); 7248 } 7249 7250 /*@C 7251 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7252 7253 Collective 7254 7255 Input Parameters: 7256 + mat - the matrix 7257 . n - the number of submatrixes to be extracted 7258 . irow - index set of rows to extract 7259 . icol - index set of columns to extract 7260 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7261 7262 Output Parameter: 7263 . submat - the array of submatrices 7264 7265 Level: advanced 7266 7267 Note: 7268 This is used by `PCGASM` 7269 7270 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7271 @*/ 7272 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7273 { 7274 PetscInt i; 7275 PetscBool eq; 7276 7277 PetscFunctionBegin; 7278 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7279 PetscValidType(mat, 1); 7280 if (n) { 7281 PetscAssertPointer(irow, 3); 7282 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7283 PetscAssertPointer(icol, 4); 7284 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7285 } 7286 PetscAssertPointer(submat, 6); 7287 if (n && scall == MAT_REUSE_MATRIX) { 7288 PetscAssertPointer(*submat, 6); 7289 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7290 } 7291 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7292 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7293 MatCheckPreallocated(mat, 1); 7294 7295 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7296 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7297 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7298 for (i = 0; i < n; i++) { 7299 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7300 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7301 } 7302 PetscFunctionReturn(PETSC_SUCCESS); 7303 } 7304 7305 /*@C 7306 MatDestroyMatrices - Destroys an array of matrices. 7307 7308 Collective 7309 7310 Input Parameters: 7311 + n - the number of local matrices 7312 - mat - the matrices (this is a pointer to the array of matrices) 7313 7314 Level: advanced 7315 7316 Notes: 7317 Frees not only the matrices, but also the array that contains the matrices 7318 7319 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7320 7321 Fortran Note: 7322 Does not free the `mat` array. 7323 7324 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7325 @*/ 7326 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7327 { 7328 PetscInt i; 7329 7330 PetscFunctionBegin; 7331 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7332 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7333 PetscAssertPointer(mat, 2); 7334 7335 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7336 7337 /* memory is allocated even if n = 0 */ 7338 PetscCall(PetscFree(*mat)); 7339 PetscFunctionReturn(PETSC_SUCCESS); 7340 } 7341 7342 /*@C 7343 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7344 7345 Collective 7346 7347 Input Parameters: 7348 + n - the number of local matrices 7349 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7350 sequence of `MatCreateSubMatrices()`) 7351 7352 Level: advanced 7353 7354 Note: 7355 Frees not only the matrices, but also the array that contains the matrices 7356 7357 Fortran Note: 7358 Does not free the `mat` array. 7359 7360 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7361 @*/ 7362 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7363 { 7364 Mat mat0; 7365 7366 PetscFunctionBegin; 7367 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7368 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7369 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7370 PetscAssertPointer(mat, 2); 7371 7372 mat0 = (*mat)[0]; 7373 if (mat0 && mat0->ops->destroysubmatrices) { 7374 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7375 } else { 7376 PetscCall(MatDestroyMatrices(n, mat)); 7377 } 7378 PetscFunctionReturn(PETSC_SUCCESS); 7379 } 7380 7381 /*@ 7382 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7383 7384 Collective 7385 7386 Input Parameter: 7387 . mat - the matrix 7388 7389 Output Parameter: 7390 . matstruct - the sequential matrix with the nonzero structure of `mat` 7391 7392 Level: developer 7393 7394 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7395 @*/ 7396 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7397 { 7398 PetscFunctionBegin; 7399 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7400 PetscAssertPointer(matstruct, 2); 7401 7402 PetscValidType(mat, 1); 7403 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7404 MatCheckPreallocated(mat, 1); 7405 7406 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7407 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7408 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7409 PetscFunctionReturn(PETSC_SUCCESS); 7410 } 7411 7412 /*@C 7413 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7414 7415 Collective 7416 7417 Input Parameter: 7418 . mat - the matrix 7419 7420 Level: advanced 7421 7422 Note: 7423 This is not needed, one can just call `MatDestroy()` 7424 7425 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7426 @*/ 7427 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7428 { 7429 PetscFunctionBegin; 7430 PetscAssertPointer(mat, 1); 7431 PetscCall(MatDestroy(mat)); 7432 PetscFunctionReturn(PETSC_SUCCESS); 7433 } 7434 7435 /*@ 7436 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7437 replaces the index sets by larger ones that represent submatrices with 7438 additional overlap. 7439 7440 Collective 7441 7442 Input Parameters: 7443 + mat - the matrix 7444 . n - the number of index sets 7445 . is - the array of index sets (these index sets will changed during the call) 7446 - ov - the additional overlap requested 7447 7448 Options Database Key: 7449 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7450 7451 Level: developer 7452 7453 Note: 7454 The computed overlap preserves the matrix block sizes when the blocks are square. 7455 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7456 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7457 7458 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7459 @*/ 7460 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7461 { 7462 PetscInt i, bs, cbs; 7463 7464 PetscFunctionBegin; 7465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7466 PetscValidType(mat, 1); 7467 PetscValidLogicalCollectiveInt(mat, n, 2); 7468 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7469 if (n) { 7470 PetscAssertPointer(is, 3); 7471 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7472 } 7473 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7474 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7475 MatCheckPreallocated(mat, 1); 7476 7477 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7478 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7479 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7480 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7481 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7482 if (bs == cbs) { 7483 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7484 } 7485 PetscFunctionReturn(PETSC_SUCCESS); 7486 } 7487 7488 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7489 7490 /*@ 7491 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7492 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7493 additional overlap. 7494 7495 Collective 7496 7497 Input Parameters: 7498 + mat - the matrix 7499 . n - the number of index sets 7500 . is - the array of index sets (these index sets will changed during the call) 7501 - ov - the additional overlap requested 7502 7503 ` Options Database Key: 7504 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7505 7506 Level: developer 7507 7508 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7509 @*/ 7510 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7511 { 7512 PetscInt i; 7513 7514 PetscFunctionBegin; 7515 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7516 PetscValidType(mat, 1); 7517 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7518 if (n) { 7519 PetscAssertPointer(is, 3); 7520 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7521 } 7522 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7523 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7524 MatCheckPreallocated(mat, 1); 7525 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7526 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7527 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7528 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7529 PetscFunctionReturn(PETSC_SUCCESS); 7530 } 7531 7532 /*@ 7533 MatGetBlockSize - Returns the matrix block size. 7534 7535 Not Collective 7536 7537 Input Parameter: 7538 . mat - the matrix 7539 7540 Output Parameter: 7541 . bs - block size 7542 7543 Level: intermediate 7544 7545 Notes: 7546 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7547 7548 If the block size has not been set yet this routine returns 1. 7549 7550 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7551 @*/ 7552 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7553 { 7554 PetscFunctionBegin; 7555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7556 PetscAssertPointer(bs, 2); 7557 *bs = PetscAbs(mat->rmap->bs); 7558 PetscFunctionReturn(PETSC_SUCCESS); 7559 } 7560 7561 /*@ 7562 MatGetBlockSizes - Returns the matrix block row and column sizes. 7563 7564 Not Collective 7565 7566 Input Parameter: 7567 . mat - the matrix 7568 7569 Output Parameters: 7570 + rbs - row block size 7571 - cbs - column block size 7572 7573 Level: intermediate 7574 7575 Notes: 7576 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7577 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7578 7579 If a block size has not been set yet this routine returns 1. 7580 7581 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7582 @*/ 7583 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7584 { 7585 PetscFunctionBegin; 7586 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7587 if (rbs) PetscAssertPointer(rbs, 2); 7588 if (cbs) PetscAssertPointer(cbs, 3); 7589 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7590 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7591 PetscFunctionReturn(PETSC_SUCCESS); 7592 } 7593 7594 /*@ 7595 MatSetBlockSize - Sets the matrix block size. 7596 7597 Logically Collective 7598 7599 Input Parameters: 7600 + mat - the matrix 7601 - bs - block size 7602 7603 Level: intermediate 7604 7605 Notes: 7606 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7607 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7608 7609 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7610 is compatible with the matrix local sizes. 7611 7612 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7613 @*/ 7614 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7615 { 7616 PetscFunctionBegin; 7617 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7618 PetscValidLogicalCollectiveInt(mat, bs, 2); 7619 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7620 PetscFunctionReturn(PETSC_SUCCESS); 7621 } 7622 7623 typedef struct { 7624 PetscInt n; 7625 IS *is; 7626 Mat *mat; 7627 PetscObjectState nonzerostate; 7628 Mat C; 7629 } EnvelopeData; 7630 7631 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7632 { 7633 EnvelopeData *edata = (EnvelopeData *)ptr; 7634 7635 PetscFunctionBegin; 7636 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7637 PetscCall(PetscFree(edata->is)); 7638 PetscCall(PetscFree(edata)); 7639 PetscFunctionReturn(PETSC_SUCCESS); 7640 } 7641 7642 /*@ 7643 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7644 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7645 7646 Collective 7647 7648 Input Parameter: 7649 . mat - the matrix 7650 7651 Level: intermediate 7652 7653 Notes: 7654 There can be zeros within the blocks 7655 7656 The blocks can overlap between processes, including laying on more than two processes 7657 7658 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7659 @*/ 7660 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7661 { 7662 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7663 PetscInt *diag, *odiag, sc; 7664 VecScatter scatter; 7665 PetscScalar *seqv; 7666 const PetscScalar *parv; 7667 const PetscInt *ia, *ja; 7668 PetscBool set, flag, done; 7669 Mat AA = mat, A; 7670 MPI_Comm comm; 7671 PetscMPIInt rank, size, tag; 7672 MPI_Status status; 7673 PetscContainer container; 7674 EnvelopeData *edata; 7675 Vec seq, par; 7676 IS isglobal; 7677 7678 PetscFunctionBegin; 7679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7680 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7681 if (!set || !flag) { 7682 /* TODO: only needs nonzero structure of transpose */ 7683 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7684 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7685 } 7686 PetscCall(MatAIJGetLocalMat(AA, &A)); 7687 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7688 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7689 7690 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7691 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7692 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7693 PetscCallMPI(MPI_Comm_size(comm, &size)); 7694 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7695 7696 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7697 7698 if (rank > 0) { 7699 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7700 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7701 } 7702 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7703 for (i = 0; i < n; i++) { 7704 env = PetscMax(env, ja[ia[i + 1] - 1]); 7705 II = rstart + i; 7706 if (env == II) { 7707 starts[lblocks] = tbs; 7708 sizes[lblocks++] = 1 + II - tbs; 7709 tbs = 1 + II; 7710 } 7711 } 7712 if (rank < size - 1) { 7713 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7714 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7715 } 7716 7717 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7718 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7719 PetscCall(MatDestroy(&A)); 7720 7721 PetscCall(PetscNew(&edata)); 7722 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7723 edata->n = lblocks; 7724 /* create IS needed for extracting blocks from the original matrix */ 7725 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7726 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7727 7728 /* Create the resulting inverse matrix structure with preallocation information */ 7729 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7730 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7731 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7732 PetscCall(MatSetType(edata->C, MATAIJ)); 7733 7734 /* Communicate the start and end of each row, from each block to the correct rank */ 7735 /* TODO: Use PetscSF instead of VecScatter */ 7736 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7737 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7738 PetscCall(VecGetArrayWrite(seq, &seqv)); 7739 for (PetscInt i = 0; i < lblocks; i++) { 7740 for (PetscInt j = 0; j < sizes[i]; j++) { 7741 seqv[cnt] = starts[i]; 7742 seqv[cnt + 1] = starts[i] + sizes[i]; 7743 cnt += 2; 7744 } 7745 } 7746 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7747 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7748 sc -= cnt; 7749 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7750 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7751 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7752 PetscCall(ISDestroy(&isglobal)); 7753 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7754 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7755 PetscCall(VecScatterDestroy(&scatter)); 7756 PetscCall(VecDestroy(&seq)); 7757 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7758 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7759 PetscCall(VecGetArrayRead(par, &parv)); 7760 cnt = 0; 7761 PetscCall(MatGetSize(mat, NULL, &n)); 7762 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7763 PetscInt start, end, d = 0, od = 0; 7764 7765 start = (PetscInt)PetscRealPart(parv[cnt]); 7766 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7767 cnt += 2; 7768 7769 if (start < cstart) { 7770 od += cstart - start + n - cend; 7771 d += cend - cstart; 7772 } else if (start < cend) { 7773 od += n - cend; 7774 d += cend - start; 7775 } else od += n - start; 7776 if (end <= cstart) { 7777 od -= cstart - end + n - cend; 7778 d -= cend - cstart; 7779 } else if (end < cend) { 7780 od -= n - cend; 7781 d -= cend - end; 7782 } else od -= n - end; 7783 7784 odiag[i] = od; 7785 diag[i] = d; 7786 } 7787 PetscCall(VecRestoreArrayRead(par, &parv)); 7788 PetscCall(VecDestroy(&par)); 7789 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7790 PetscCall(PetscFree2(diag, odiag)); 7791 PetscCall(PetscFree2(sizes, starts)); 7792 7793 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7794 PetscCall(PetscContainerSetPointer(container, edata)); 7795 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7796 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7797 PetscCall(PetscObjectDereference((PetscObject)container)); 7798 PetscFunctionReturn(PETSC_SUCCESS); 7799 } 7800 7801 /*@ 7802 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7803 7804 Collective 7805 7806 Input Parameters: 7807 + A - the matrix 7808 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7809 7810 Output Parameter: 7811 . C - matrix with inverted block diagonal of `A` 7812 7813 Level: advanced 7814 7815 Note: 7816 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7817 7818 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7819 @*/ 7820 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7821 { 7822 PetscContainer container; 7823 EnvelopeData *edata; 7824 PetscObjectState nonzerostate; 7825 7826 PetscFunctionBegin; 7827 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7828 if (!container) { 7829 PetscCall(MatComputeVariableBlockEnvelope(A)); 7830 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7831 } 7832 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7833 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7834 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7835 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7836 7837 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7838 *C = edata->C; 7839 7840 for (PetscInt i = 0; i < edata->n; i++) { 7841 Mat D; 7842 PetscScalar *dvalues; 7843 7844 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7845 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7846 PetscCall(MatSeqDenseInvert(D)); 7847 PetscCall(MatDenseGetArray(D, &dvalues)); 7848 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7849 PetscCall(MatDestroy(&D)); 7850 } 7851 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7852 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7853 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7854 PetscFunctionReturn(PETSC_SUCCESS); 7855 } 7856 7857 /*@ 7858 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7859 7860 Not Collective 7861 7862 Input Parameters: 7863 + mat - the matrix 7864 . nblocks - the number of blocks on this process, each block can only exist on a single process 7865 - bsizes - the block sizes 7866 7867 Level: intermediate 7868 7869 Notes: 7870 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7871 7872 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. 7873 7874 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7875 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7876 @*/ 7877 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7878 { 7879 PetscInt ncnt = 0, nlocal; 7880 7881 PetscFunctionBegin; 7882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7883 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7884 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); 7885 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7886 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); 7887 PetscCall(PetscFree(mat->bsizes)); 7888 mat->nblocks = nblocks; 7889 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7890 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7891 PetscFunctionReturn(PETSC_SUCCESS); 7892 } 7893 7894 /*@C 7895 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7896 7897 Not Collective; No Fortran Support 7898 7899 Input Parameter: 7900 . mat - the matrix 7901 7902 Output Parameters: 7903 + nblocks - the number of blocks on this process 7904 - bsizes - the block sizes 7905 7906 Level: intermediate 7907 7908 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7909 @*/ 7910 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7911 { 7912 PetscFunctionBegin; 7913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7914 if (nblocks) *nblocks = mat->nblocks; 7915 if (bsizes) *bsizes = mat->bsizes; 7916 PetscFunctionReturn(PETSC_SUCCESS); 7917 } 7918 7919 /*@ 7920 MatSetBlockSizes - Sets the matrix block row and column sizes. 7921 7922 Logically Collective 7923 7924 Input Parameters: 7925 + mat - the matrix 7926 . rbs - row block size 7927 - cbs - column block size 7928 7929 Level: intermediate 7930 7931 Notes: 7932 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7933 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7934 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7935 7936 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7937 are compatible with the matrix local sizes. 7938 7939 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7940 7941 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7942 @*/ 7943 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7944 { 7945 PetscFunctionBegin; 7946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7947 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7948 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7949 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7950 if (mat->rmap->refcnt) { 7951 ISLocalToGlobalMapping l2g = NULL; 7952 PetscLayout nmap = NULL; 7953 7954 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7955 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7956 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7957 mat->rmap = nmap; 7958 mat->rmap->mapping = l2g; 7959 } 7960 if (mat->cmap->refcnt) { 7961 ISLocalToGlobalMapping l2g = NULL; 7962 PetscLayout nmap = NULL; 7963 7964 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7965 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7966 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7967 mat->cmap = nmap; 7968 mat->cmap->mapping = l2g; 7969 } 7970 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7971 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7972 PetscFunctionReturn(PETSC_SUCCESS); 7973 } 7974 7975 /*@ 7976 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7977 7978 Logically Collective 7979 7980 Input Parameters: 7981 + mat - the matrix 7982 . fromRow - matrix from which to copy row block size 7983 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7984 7985 Level: developer 7986 7987 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7988 @*/ 7989 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7990 { 7991 PetscFunctionBegin; 7992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7993 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7994 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7995 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7996 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7997 PetscFunctionReturn(PETSC_SUCCESS); 7998 } 7999 8000 /*@ 8001 MatResidual - Default routine to calculate the residual r = b - Ax 8002 8003 Collective 8004 8005 Input Parameters: 8006 + mat - the matrix 8007 . b - the right-hand-side 8008 - x - the approximate solution 8009 8010 Output Parameter: 8011 . r - location to store the residual 8012 8013 Level: developer 8014 8015 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8016 @*/ 8017 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8018 { 8019 PetscFunctionBegin; 8020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8021 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8022 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8023 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8024 PetscValidType(mat, 1); 8025 MatCheckPreallocated(mat, 1); 8026 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8027 if (!mat->ops->residual) { 8028 PetscCall(MatMult(mat, x, r)); 8029 PetscCall(VecAYPX(r, -1.0, b)); 8030 } else { 8031 PetscUseTypeMethod(mat, residual, b, x, r); 8032 } 8033 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8034 PetscFunctionReturn(PETSC_SUCCESS); 8035 } 8036 8037 /*MC 8038 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8039 8040 Synopsis: 8041 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8042 8043 Not Collective 8044 8045 Input Parameters: 8046 + A - the matrix 8047 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8048 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8049 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8050 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8051 always used. 8052 8053 Output Parameters: 8054 + n - number of local rows in the (possibly compressed) matrix 8055 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8056 . ja - the column indices 8057 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8058 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8059 8060 Level: developer 8061 8062 Note: 8063 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8064 8065 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8066 M*/ 8067 8068 /*MC 8069 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8070 8071 Synopsis: 8072 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8073 8074 Not Collective 8075 8076 Input Parameters: 8077 + A - the matrix 8078 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8079 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8080 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8081 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8082 always used. 8083 . n - number of local rows in the (possibly compressed) matrix 8084 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8085 . ja - the column indices 8086 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8087 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8088 8089 Level: developer 8090 8091 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8092 M*/ 8093 8094 /*@C 8095 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8096 8097 Collective 8098 8099 Input Parameters: 8100 + mat - the matrix 8101 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8102 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8103 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8104 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8105 always used. 8106 8107 Output Parameters: 8108 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8109 . 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 8110 . ja - the column indices, use `NULL` if not needed 8111 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8112 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8113 8114 Level: developer 8115 8116 Notes: 8117 You CANNOT change any of the ia[] or ja[] values. 8118 8119 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8120 8121 Fortran Notes: 8122 Use 8123 .vb 8124 PetscInt, pointer :: ia(:),ja(:) 8125 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8126 ! Access the ith and jth entries via ia(i) and ja(j) 8127 .ve 8128 8129 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8130 8131 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8132 @*/ 8133 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8134 { 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8137 PetscValidType(mat, 1); 8138 if (n) PetscAssertPointer(n, 5); 8139 if (ia) PetscAssertPointer(ia, 6); 8140 if (ja) PetscAssertPointer(ja, 7); 8141 if (done) PetscAssertPointer(done, 8); 8142 MatCheckPreallocated(mat, 1); 8143 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8144 else { 8145 if (done) *done = PETSC_TRUE; 8146 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8147 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8148 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8149 } 8150 PetscFunctionReturn(PETSC_SUCCESS); 8151 } 8152 8153 /*@C 8154 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8155 8156 Collective 8157 8158 Input Parameters: 8159 + mat - the matrix 8160 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8161 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8162 symmetrized 8163 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8164 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8165 always used. 8166 . n - number of columns in the (possibly compressed) matrix 8167 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8168 - ja - the row indices 8169 8170 Output Parameter: 8171 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8172 8173 Level: developer 8174 8175 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8176 @*/ 8177 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8178 { 8179 PetscFunctionBegin; 8180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8181 PetscValidType(mat, 1); 8182 PetscAssertPointer(n, 5); 8183 if (ia) PetscAssertPointer(ia, 6); 8184 if (ja) PetscAssertPointer(ja, 7); 8185 PetscAssertPointer(done, 8); 8186 MatCheckPreallocated(mat, 1); 8187 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8188 else { 8189 *done = PETSC_TRUE; 8190 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8191 } 8192 PetscFunctionReturn(PETSC_SUCCESS); 8193 } 8194 8195 /*@C 8196 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8197 8198 Collective 8199 8200 Input Parameters: 8201 + mat - the matrix 8202 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8203 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8204 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8205 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8206 always used. 8207 . n - size of (possibly compressed) matrix 8208 . ia - the row pointers 8209 - ja - the column indices 8210 8211 Output Parameter: 8212 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8213 8214 Level: developer 8215 8216 Note: 8217 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8218 us of the array after it has been restored. If you pass `NULL`, it will 8219 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8220 8221 Fortran Note: 8222 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8223 8224 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8225 @*/ 8226 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8227 { 8228 PetscFunctionBegin; 8229 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8230 PetscValidType(mat, 1); 8231 if (ia) PetscAssertPointer(ia, 6); 8232 if (ja) PetscAssertPointer(ja, 7); 8233 if (done) PetscAssertPointer(done, 8); 8234 MatCheckPreallocated(mat, 1); 8235 8236 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8237 else { 8238 if (done) *done = PETSC_TRUE; 8239 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8240 if (n) *n = 0; 8241 if (ia) *ia = NULL; 8242 if (ja) *ja = NULL; 8243 } 8244 PetscFunctionReturn(PETSC_SUCCESS); 8245 } 8246 8247 /*@C 8248 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8249 8250 Collective 8251 8252 Input Parameters: 8253 + mat - the matrix 8254 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8255 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8256 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8257 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8258 always used. 8259 8260 Output Parameters: 8261 + n - size of (possibly compressed) matrix 8262 . ia - the column pointers 8263 . ja - the row indices 8264 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8265 8266 Level: developer 8267 8268 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8269 @*/ 8270 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8271 { 8272 PetscFunctionBegin; 8273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8274 PetscValidType(mat, 1); 8275 if (ia) PetscAssertPointer(ia, 6); 8276 if (ja) PetscAssertPointer(ja, 7); 8277 PetscAssertPointer(done, 8); 8278 MatCheckPreallocated(mat, 1); 8279 8280 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8281 else { 8282 *done = PETSC_TRUE; 8283 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8284 if (n) *n = 0; 8285 if (ia) *ia = NULL; 8286 if (ja) *ja = NULL; 8287 } 8288 PetscFunctionReturn(PETSC_SUCCESS); 8289 } 8290 8291 /*@ 8292 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8293 `MatGetColumnIJ()`. 8294 8295 Collective 8296 8297 Input Parameters: 8298 + mat - the matrix 8299 . ncolors - maximum color value 8300 . n - number of entries in colorarray 8301 - colorarray - array indicating color for each column 8302 8303 Output Parameter: 8304 . iscoloring - coloring generated using colorarray information 8305 8306 Level: developer 8307 8308 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8309 @*/ 8310 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8311 { 8312 PetscFunctionBegin; 8313 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8314 PetscValidType(mat, 1); 8315 PetscAssertPointer(colorarray, 4); 8316 PetscAssertPointer(iscoloring, 5); 8317 MatCheckPreallocated(mat, 1); 8318 8319 if (!mat->ops->coloringpatch) { 8320 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8321 } else { 8322 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8323 } 8324 PetscFunctionReturn(PETSC_SUCCESS); 8325 } 8326 8327 /*@ 8328 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8329 8330 Logically Collective 8331 8332 Input Parameter: 8333 . mat - the factored matrix to be reset 8334 8335 Level: developer 8336 8337 Notes: 8338 This routine should be used only with factored matrices formed by in-place 8339 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8340 format). This option can save memory, for example, when solving nonlinear 8341 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8342 ILU(0) preconditioner. 8343 8344 One can specify in-place ILU(0) factorization by calling 8345 .vb 8346 PCType(pc,PCILU); 8347 PCFactorSeUseInPlace(pc); 8348 .ve 8349 or by using the options -pc_type ilu -pc_factor_in_place 8350 8351 In-place factorization ILU(0) can also be used as a local 8352 solver for the blocks within the block Jacobi or additive Schwarz 8353 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8354 for details on setting local solver options. 8355 8356 Most users should employ the `KSP` interface for linear solvers 8357 instead of working directly with matrix algebra routines such as this. 8358 See, e.g., `KSPCreate()`. 8359 8360 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8361 @*/ 8362 PetscErrorCode MatSetUnfactored(Mat mat) 8363 { 8364 PetscFunctionBegin; 8365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8366 PetscValidType(mat, 1); 8367 MatCheckPreallocated(mat, 1); 8368 mat->factortype = MAT_FACTOR_NONE; 8369 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8370 PetscUseTypeMethod(mat, setunfactored); 8371 PetscFunctionReturn(PETSC_SUCCESS); 8372 } 8373 8374 /*MC 8375 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8376 8377 Synopsis: 8378 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8379 8380 Not Collective 8381 8382 Input Parameter: 8383 . x - matrix 8384 8385 Output Parameters: 8386 + xx_v - the Fortran pointer to the array 8387 - ierr - error code 8388 8389 Example of Usage: 8390 .vb 8391 PetscScalar, pointer xx_v(:,:) 8392 .... 8393 call MatDenseGetArrayF90(x,xx_v,ierr) 8394 a = xx_v(3) 8395 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8396 .ve 8397 8398 Level: advanced 8399 8400 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8401 M*/ 8402 8403 /*MC 8404 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8405 accessed with `MatDenseGetArrayF90()`. 8406 8407 Synopsis: 8408 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8409 8410 Not Collective 8411 8412 Input Parameters: 8413 + x - matrix 8414 - xx_v - the Fortran90 pointer to the array 8415 8416 Output Parameter: 8417 . ierr - error code 8418 8419 Example of Usage: 8420 .vb 8421 PetscScalar, pointer xx_v(:,:) 8422 .... 8423 call MatDenseGetArrayF90(x,xx_v,ierr) 8424 a = xx_v(3) 8425 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8426 .ve 8427 8428 Level: advanced 8429 8430 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8431 M*/ 8432 8433 /*MC 8434 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8435 8436 Synopsis: 8437 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8438 8439 Not Collective 8440 8441 Input Parameter: 8442 . x - matrix 8443 8444 Output Parameters: 8445 + xx_v - the Fortran pointer to the array 8446 - ierr - error code 8447 8448 Example of Usage: 8449 .vb 8450 PetscScalar, pointer xx_v(:) 8451 .... 8452 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8453 a = xx_v(3) 8454 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8455 .ve 8456 8457 Level: advanced 8458 8459 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8460 M*/ 8461 8462 /*MC 8463 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8464 accessed with `MatSeqAIJGetArrayF90()`. 8465 8466 Synopsis: 8467 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8468 8469 Not Collective 8470 8471 Input Parameters: 8472 + x - matrix 8473 - xx_v - the Fortran90 pointer to the array 8474 8475 Output Parameter: 8476 . ierr - error code 8477 8478 Example of Usage: 8479 .vb 8480 PetscScalar, pointer xx_v(:) 8481 .... 8482 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8483 a = xx_v(3) 8484 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8485 .ve 8486 8487 Level: advanced 8488 8489 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8490 M*/ 8491 8492 /*@ 8493 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8494 as the original matrix. 8495 8496 Collective 8497 8498 Input Parameters: 8499 + mat - the original matrix 8500 . isrow - parallel `IS` containing the rows this processor should obtain 8501 . 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. 8502 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8503 8504 Output Parameter: 8505 . newmat - the new submatrix, of the same type as the original matrix 8506 8507 Level: advanced 8508 8509 Notes: 8510 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8511 8512 Some matrix types place restrictions on the row and column indices, such 8513 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; 8514 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8515 8516 The index sets may not have duplicate entries. 8517 8518 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8519 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8520 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8521 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8522 you are finished using it. 8523 8524 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8525 the input matrix. 8526 8527 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8528 8529 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8530 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8531 8532 Example usage: 8533 Consider the following 8x8 matrix with 34 non-zero values, that is 8534 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8535 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8536 as follows 8537 .vb 8538 1 2 0 | 0 3 0 | 0 4 8539 Proc0 0 5 6 | 7 0 0 | 8 0 8540 9 0 10 | 11 0 0 | 12 0 8541 ------------------------------------- 8542 13 0 14 | 15 16 17 | 0 0 8543 Proc1 0 18 0 | 19 20 21 | 0 0 8544 0 0 0 | 22 23 0 | 24 0 8545 ------------------------------------- 8546 Proc2 25 26 27 | 0 0 28 | 29 0 8547 30 0 0 | 31 32 33 | 0 34 8548 .ve 8549 8550 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8551 8552 .vb 8553 2 0 | 0 3 0 | 0 8554 Proc0 5 6 | 7 0 0 | 8 8555 ------------------------------- 8556 Proc1 18 0 | 19 20 21 | 0 8557 ------------------------------- 8558 Proc2 26 27 | 0 0 28 | 29 8559 0 0 | 31 32 33 | 0 8560 .ve 8561 8562 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8563 @*/ 8564 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8565 { 8566 PetscMPIInt size; 8567 Mat *local; 8568 IS iscoltmp; 8569 PetscBool flg; 8570 8571 PetscFunctionBegin; 8572 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8573 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8574 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8575 PetscAssertPointer(newmat, 5); 8576 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8577 PetscValidType(mat, 1); 8578 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8579 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8580 8581 MatCheckPreallocated(mat, 1); 8582 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8583 8584 if (!iscol || isrow == iscol) { 8585 PetscBool stride; 8586 PetscMPIInt grabentirematrix = 0, grab; 8587 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8588 if (stride) { 8589 PetscInt first, step, n, rstart, rend; 8590 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8591 if (step == 1) { 8592 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8593 if (rstart == first) { 8594 PetscCall(ISGetLocalSize(isrow, &n)); 8595 if (n == rend - rstart) grabentirematrix = 1; 8596 } 8597 } 8598 } 8599 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8600 if (grab) { 8601 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8602 if (cll == MAT_INITIAL_MATRIX) { 8603 *newmat = mat; 8604 PetscCall(PetscObjectReference((PetscObject)mat)); 8605 } 8606 PetscFunctionReturn(PETSC_SUCCESS); 8607 } 8608 } 8609 8610 if (!iscol) { 8611 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8612 } else { 8613 iscoltmp = iscol; 8614 } 8615 8616 /* if original matrix is on just one processor then use submatrix generated */ 8617 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8618 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8619 goto setproperties; 8620 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8621 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8622 *newmat = *local; 8623 PetscCall(PetscFree(local)); 8624 goto setproperties; 8625 } else if (!mat->ops->createsubmatrix) { 8626 /* Create a new matrix type that implements the operation using the full matrix */ 8627 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8628 switch (cll) { 8629 case MAT_INITIAL_MATRIX: 8630 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8631 break; 8632 case MAT_REUSE_MATRIX: 8633 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8634 break; 8635 default: 8636 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8637 } 8638 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8639 goto setproperties; 8640 } 8641 8642 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8643 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8644 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8645 8646 setproperties: 8647 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8648 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8649 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8650 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8651 PetscFunctionReturn(PETSC_SUCCESS); 8652 } 8653 8654 /*@ 8655 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8656 8657 Not Collective 8658 8659 Input Parameters: 8660 + A - the matrix we wish to propagate options from 8661 - B - the matrix we wish to propagate options to 8662 8663 Level: beginner 8664 8665 Note: 8666 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8667 8668 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8669 @*/ 8670 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8671 { 8672 PetscFunctionBegin; 8673 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8674 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8675 B->symmetry_eternal = A->symmetry_eternal; 8676 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8677 B->symmetric = A->symmetric; 8678 B->structurally_symmetric = A->structurally_symmetric; 8679 B->spd = A->spd; 8680 B->hermitian = A->hermitian; 8681 PetscFunctionReturn(PETSC_SUCCESS); 8682 } 8683 8684 /*@ 8685 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8686 used during the assembly process to store values that belong to 8687 other processors. 8688 8689 Not Collective 8690 8691 Input Parameters: 8692 + mat - the matrix 8693 . size - the initial size of the stash. 8694 - bsize - the initial size of the block-stash(if used). 8695 8696 Options Database Keys: 8697 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8698 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8699 8700 Level: intermediate 8701 8702 Notes: 8703 The block-stash is used for values set with `MatSetValuesBlocked()` while 8704 the stash is used for values set with `MatSetValues()` 8705 8706 Run with the option -info and look for output of the form 8707 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8708 to determine the appropriate value, MM, to use for size and 8709 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8710 to determine the value, BMM to use for bsize 8711 8712 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8713 @*/ 8714 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8715 { 8716 PetscFunctionBegin; 8717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8718 PetscValidType(mat, 1); 8719 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8720 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8721 PetscFunctionReturn(PETSC_SUCCESS); 8722 } 8723 8724 /*@ 8725 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8726 the matrix 8727 8728 Neighbor-wise Collective 8729 8730 Input Parameters: 8731 + A - the matrix 8732 . x - the vector to be multiplied by the interpolation operator 8733 - y - the vector to be added to the result 8734 8735 Output Parameter: 8736 . w - the resulting vector 8737 8738 Level: intermediate 8739 8740 Notes: 8741 `w` may be the same vector as `y`. 8742 8743 This allows one to use either the restriction or interpolation (its transpose) 8744 matrix to do the interpolation 8745 8746 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8747 @*/ 8748 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8749 { 8750 PetscInt M, N, Ny; 8751 8752 PetscFunctionBegin; 8753 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8754 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8755 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8756 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8757 PetscCall(MatGetSize(A, &M, &N)); 8758 PetscCall(VecGetSize(y, &Ny)); 8759 if (M == Ny) { 8760 PetscCall(MatMultAdd(A, x, y, w)); 8761 } else { 8762 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8763 } 8764 PetscFunctionReturn(PETSC_SUCCESS); 8765 } 8766 8767 /*@ 8768 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8769 the matrix 8770 8771 Neighbor-wise Collective 8772 8773 Input Parameters: 8774 + A - the matrix 8775 - x - the vector to be interpolated 8776 8777 Output Parameter: 8778 . y - the resulting vector 8779 8780 Level: intermediate 8781 8782 Note: 8783 This allows one to use either the restriction or interpolation (its transpose) 8784 matrix to do the interpolation 8785 8786 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8787 @*/ 8788 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8789 { 8790 PetscInt M, N, Ny; 8791 8792 PetscFunctionBegin; 8793 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8794 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8795 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8796 PetscCall(MatGetSize(A, &M, &N)); 8797 PetscCall(VecGetSize(y, &Ny)); 8798 if (M == Ny) { 8799 PetscCall(MatMult(A, x, y)); 8800 } else { 8801 PetscCall(MatMultTranspose(A, x, y)); 8802 } 8803 PetscFunctionReturn(PETSC_SUCCESS); 8804 } 8805 8806 /*@ 8807 MatRestrict - $y = A*x$ or $A^T*x$ 8808 8809 Neighbor-wise Collective 8810 8811 Input Parameters: 8812 + A - the matrix 8813 - x - the vector to be restricted 8814 8815 Output Parameter: 8816 . y - the resulting vector 8817 8818 Level: intermediate 8819 8820 Note: 8821 This allows one to use either the restriction or interpolation (its transpose) 8822 matrix to do the restriction 8823 8824 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8825 @*/ 8826 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8827 { 8828 PetscInt M, N, Nx; 8829 8830 PetscFunctionBegin; 8831 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8832 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8833 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8834 PetscCall(MatGetSize(A, &M, &N)); 8835 PetscCall(VecGetSize(x, &Nx)); 8836 if (M == Nx) { 8837 PetscCall(MatMultTranspose(A, x, y)); 8838 } else { 8839 PetscCall(MatMult(A, x, y)); 8840 } 8841 PetscFunctionReturn(PETSC_SUCCESS); 8842 } 8843 8844 /*@ 8845 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8846 8847 Neighbor-wise Collective 8848 8849 Input Parameters: 8850 + A - the matrix 8851 . x - the input dense matrix to be multiplied 8852 - w - the input dense matrix to be added to the result 8853 8854 Output Parameter: 8855 . y - the output dense matrix 8856 8857 Level: intermediate 8858 8859 Note: 8860 This allows one to use either the restriction or interpolation (its transpose) 8861 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8862 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8863 8864 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8865 @*/ 8866 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8867 { 8868 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8869 PetscBool trans = PETSC_TRUE; 8870 MatReuse reuse = MAT_INITIAL_MATRIX; 8871 8872 PetscFunctionBegin; 8873 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8874 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8875 PetscValidType(x, 2); 8876 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8877 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8878 PetscCall(MatGetSize(A, &M, &N)); 8879 PetscCall(MatGetSize(x, &Mx, &Nx)); 8880 if (N == Mx) trans = PETSC_FALSE; 8881 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); 8882 Mo = trans ? N : M; 8883 if (*y) { 8884 PetscCall(MatGetSize(*y, &My, &Ny)); 8885 if (Mo == My && Nx == Ny) { 8886 reuse = MAT_REUSE_MATRIX; 8887 } else { 8888 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); 8889 PetscCall(MatDestroy(y)); 8890 } 8891 } 8892 8893 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8894 PetscBool flg; 8895 8896 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8897 if (w) { 8898 PetscInt My, Ny, Mw, Nw; 8899 8900 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8901 PetscCall(MatGetSize(*y, &My, &Ny)); 8902 PetscCall(MatGetSize(w, &Mw, &Nw)); 8903 if (!flg || My != Mw || Ny != Nw) w = NULL; 8904 } 8905 if (!w) { 8906 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8907 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8908 PetscCall(PetscObjectDereference((PetscObject)w)); 8909 } else { 8910 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8911 } 8912 } 8913 if (!trans) { 8914 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8915 } else { 8916 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8917 } 8918 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8919 PetscFunctionReturn(PETSC_SUCCESS); 8920 } 8921 8922 /*@ 8923 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8924 8925 Neighbor-wise Collective 8926 8927 Input Parameters: 8928 + A - the matrix 8929 - x - the input dense matrix 8930 8931 Output Parameter: 8932 . y - the output dense matrix 8933 8934 Level: intermediate 8935 8936 Note: 8937 This allows one to use either the restriction or interpolation (its transpose) 8938 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8939 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8940 8941 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8942 @*/ 8943 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8944 { 8945 PetscFunctionBegin; 8946 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8947 PetscFunctionReturn(PETSC_SUCCESS); 8948 } 8949 8950 /*@ 8951 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8952 8953 Neighbor-wise Collective 8954 8955 Input Parameters: 8956 + A - the matrix 8957 - x - the input dense matrix 8958 8959 Output Parameter: 8960 . y - the output dense matrix 8961 8962 Level: intermediate 8963 8964 Note: 8965 This allows one to use either the restriction or interpolation (its transpose) 8966 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8967 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8968 8969 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8970 @*/ 8971 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8972 { 8973 PetscFunctionBegin; 8974 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8975 PetscFunctionReturn(PETSC_SUCCESS); 8976 } 8977 8978 /*@ 8979 MatGetNullSpace - retrieves the null space of a matrix. 8980 8981 Logically Collective 8982 8983 Input Parameters: 8984 + mat - the matrix 8985 - nullsp - the null space object 8986 8987 Level: developer 8988 8989 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8990 @*/ 8991 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8992 { 8993 PetscFunctionBegin; 8994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8995 PetscAssertPointer(nullsp, 2); 8996 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8997 PetscFunctionReturn(PETSC_SUCCESS); 8998 } 8999 9000 /*@C 9001 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9002 9003 Logically Collective 9004 9005 Input Parameters: 9006 + n - the number of matrices 9007 - mat - the array of matrices 9008 9009 Output Parameters: 9010 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9011 9012 Level: developer 9013 9014 Note: 9015 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9016 9017 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9018 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9019 @*/ 9020 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9021 { 9022 PetscFunctionBegin; 9023 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9024 PetscAssertPointer(mat, 2); 9025 PetscAssertPointer(nullsp, 3); 9026 9027 PetscCall(PetscCalloc1(3 * n, nullsp)); 9028 for (PetscInt i = 0; i < n; i++) { 9029 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9030 (*nullsp)[i] = mat[i]->nullsp; 9031 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9032 (*nullsp)[n + i] = mat[i]->nearnullsp; 9033 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9034 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9035 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9036 } 9037 PetscFunctionReturn(PETSC_SUCCESS); 9038 } 9039 9040 /*@C 9041 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9042 9043 Logically Collective 9044 9045 Input Parameters: 9046 + n - the number of matrices 9047 . mat - the array of matrices 9048 - nullsp - an array of null spaces 9049 9050 Level: developer 9051 9052 Note: 9053 Call `MatGetNullSpaces()` to create `nullsp` 9054 9055 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9056 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9057 @*/ 9058 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9059 { 9060 PetscFunctionBegin; 9061 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9062 PetscAssertPointer(mat, 2); 9063 PetscAssertPointer(nullsp, 3); 9064 PetscAssertPointer(*nullsp, 3); 9065 9066 for (PetscInt i = 0; i < n; i++) { 9067 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9068 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9069 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9070 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9071 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9072 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9073 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9074 } 9075 PetscCall(PetscFree(*nullsp)); 9076 PetscFunctionReturn(PETSC_SUCCESS); 9077 } 9078 9079 /*@ 9080 MatSetNullSpace - attaches a null space to a matrix. 9081 9082 Logically Collective 9083 9084 Input Parameters: 9085 + mat - the matrix 9086 - nullsp - the null space object 9087 9088 Level: advanced 9089 9090 Notes: 9091 This null space is used by the `KSP` linear solvers to solve singular systems. 9092 9093 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` 9094 9095 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 9096 to zero but the linear system will still be solved in a least squares sense. 9097 9098 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9099 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)$. 9100 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 9101 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 9102 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$). 9103 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9104 9105 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9106 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9107 routine also automatically calls `MatSetTransposeNullSpace()`. 9108 9109 The user should call `MatNullSpaceDestroy()`. 9110 9111 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9112 `KSPSetPCSide()` 9113 @*/ 9114 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9115 { 9116 PetscFunctionBegin; 9117 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9118 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9119 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9120 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9121 mat->nullsp = nullsp; 9122 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9123 PetscFunctionReturn(PETSC_SUCCESS); 9124 } 9125 9126 /*@ 9127 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9128 9129 Logically Collective 9130 9131 Input Parameters: 9132 + mat - the matrix 9133 - nullsp - the null space object 9134 9135 Level: developer 9136 9137 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9138 @*/ 9139 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9140 { 9141 PetscFunctionBegin; 9142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9143 PetscValidType(mat, 1); 9144 PetscAssertPointer(nullsp, 2); 9145 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9146 PetscFunctionReturn(PETSC_SUCCESS); 9147 } 9148 9149 /*@ 9150 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9151 9152 Logically Collective 9153 9154 Input Parameters: 9155 + mat - the matrix 9156 - nullsp - the null space object 9157 9158 Level: advanced 9159 9160 Notes: 9161 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9162 9163 See `MatSetNullSpace()` 9164 9165 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9166 @*/ 9167 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9168 { 9169 PetscFunctionBegin; 9170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9171 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9172 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9173 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9174 mat->transnullsp = nullsp; 9175 PetscFunctionReturn(PETSC_SUCCESS); 9176 } 9177 9178 /*@ 9179 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9180 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9181 9182 Logically Collective 9183 9184 Input Parameters: 9185 + mat - the matrix 9186 - nullsp - the null space object 9187 9188 Level: advanced 9189 9190 Notes: 9191 Overwrites any previous near null space that may have been attached 9192 9193 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9194 9195 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9196 @*/ 9197 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9198 { 9199 PetscFunctionBegin; 9200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9201 PetscValidType(mat, 1); 9202 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9203 MatCheckPreallocated(mat, 1); 9204 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9205 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9206 mat->nearnullsp = nullsp; 9207 PetscFunctionReturn(PETSC_SUCCESS); 9208 } 9209 9210 /*@ 9211 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9212 9213 Not Collective 9214 9215 Input Parameter: 9216 . mat - the matrix 9217 9218 Output Parameter: 9219 . nullsp - the null space object, `NULL` if not set 9220 9221 Level: advanced 9222 9223 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9224 @*/ 9225 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9226 { 9227 PetscFunctionBegin; 9228 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9229 PetscValidType(mat, 1); 9230 PetscAssertPointer(nullsp, 2); 9231 MatCheckPreallocated(mat, 1); 9232 *nullsp = mat->nearnullsp; 9233 PetscFunctionReturn(PETSC_SUCCESS); 9234 } 9235 9236 /*@ 9237 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9238 9239 Collective 9240 9241 Input Parameters: 9242 + mat - the matrix 9243 . row - row/column permutation 9244 - info - information on desired factorization process 9245 9246 Level: developer 9247 9248 Notes: 9249 Probably really in-place only when level of fill is zero, otherwise allocates 9250 new space to store factored matrix and deletes previous memory. 9251 9252 Most users should employ the `KSP` interface for linear solvers 9253 instead of working directly with matrix algebra routines such as this. 9254 See, e.g., `KSPCreate()`. 9255 9256 Developer Note: 9257 The Fortran interface is not autogenerated as the 9258 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9259 9260 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9261 @*/ 9262 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9263 { 9264 PetscFunctionBegin; 9265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9266 PetscValidType(mat, 1); 9267 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9268 PetscAssertPointer(info, 3); 9269 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9272 MatCheckPreallocated(mat, 1); 9273 PetscUseTypeMethod(mat, iccfactor, row, info); 9274 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9275 PetscFunctionReturn(PETSC_SUCCESS); 9276 } 9277 9278 /*@ 9279 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9280 ghosted ones. 9281 9282 Not Collective 9283 9284 Input Parameters: 9285 + mat - the matrix 9286 - diag - the diagonal values, including ghost ones 9287 9288 Level: developer 9289 9290 Notes: 9291 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9292 9293 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9294 9295 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9296 @*/ 9297 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9298 { 9299 PetscMPIInt size; 9300 9301 PetscFunctionBegin; 9302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9303 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9304 PetscValidType(mat, 1); 9305 9306 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9307 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9308 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9309 if (size == 1) { 9310 PetscInt n, m; 9311 PetscCall(VecGetSize(diag, &n)); 9312 PetscCall(MatGetSize(mat, NULL, &m)); 9313 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9314 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9315 } else { 9316 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9317 } 9318 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9319 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9320 PetscFunctionReturn(PETSC_SUCCESS); 9321 } 9322 9323 /*@ 9324 MatGetInertia - Gets the inertia from a factored matrix 9325 9326 Collective 9327 9328 Input Parameter: 9329 . mat - the matrix 9330 9331 Output Parameters: 9332 + nneg - number of negative eigenvalues 9333 . nzero - number of zero eigenvalues 9334 - npos - number of positive eigenvalues 9335 9336 Level: advanced 9337 9338 Note: 9339 Matrix must have been factored by `MatCholeskyFactor()` 9340 9341 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9342 @*/ 9343 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9344 { 9345 PetscFunctionBegin; 9346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9347 PetscValidType(mat, 1); 9348 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9349 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9350 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9351 PetscFunctionReturn(PETSC_SUCCESS); 9352 } 9353 9354 /*@C 9355 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9356 9357 Neighbor-wise Collective 9358 9359 Input Parameters: 9360 + mat - the factored matrix obtained with `MatGetFactor()` 9361 - b - the right-hand-side vectors 9362 9363 Output Parameter: 9364 . x - the result vectors 9365 9366 Level: developer 9367 9368 Note: 9369 The vectors `b` and `x` cannot be the same. I.e., one cannot 9370 call `MatSolves`(A,x,x). 9371 9372 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9373 @*/ 9374 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9375 { 9376 PetscFunctionBegin; 9377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9378 PetscValidType(mat, 1); 9379 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9380 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9381 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9382 9383 MatCheckPreallocated(mat, 1); 9384 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9385 PetscUseTypeMethod(mat, solves, b, x); 9386 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9387 PetscFunctionReturn(PETSC_SUCCESS); 9388 } 9389 9390 /*@ 9391 MatIsSymmetric - Test whether a matrix is symmetric 9392 9393 Collective 9394 9395 Input Parameters: 9396 + A - the matrix to test 9397 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9398 9399 Output Parameter: 9400 . flg - the result 9401 9402 Level: intermediate 9403 9404 Notes: 9405 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9406 9407 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9408 9409 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9410 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9411 9412 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9413 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9414 @*/ 9415 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9416 { 9417 PetscFunctionBegin; 9418 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9419 PetscAssertPointer(flg, 3); 9420 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9421 else { 9422 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9423 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9424 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9425 } 9426 PetscFunctionReturn(PETSC_SUCCESS); 9427 } 9428 9429 /*@ 9430 MatIsHermitian - Test whether a matrix is Hermitian 9431 9432 Collective 9433 9434 Input Parameters: 9435 + A - the matrix to test 9436 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9437 9438 Output Parameter: 9439 . flg - the result 9440 9441 Level: intermediate 9442 9443 Notes: 9444 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9445 9446 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9447 9448 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9449 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9450 9451 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9452 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9453 @*/ 9454 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9455 { 9456 PetscFunctionBegin; 9457 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9458 PetscAssertPointer(flg, 3); 9459 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9460 else { 9461 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9462 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9463 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9464 } 9465 PetscFunctionReturn(PETSC_SUCCESS); 9466 } 9467 9468 /*@ 9469 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9470 9471 Not Collective 9472 9473 Input Parameter: 9474 . A - the matrix to check 9475 9476 Output Parameters: 9477 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9478 - flg - the result (only valid if set is `PETSC_TRUE`) 9479 9480 Level: advanced 9481 9482 Notes: 9483 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9484 if you want it explicitly checked 9485 9486 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9487 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9488 9489 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9490 @*/ 9491 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9492 { 9493 PetscFunctionBegin; 9494 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9495 PetscAssertPointer(set, 2); 9496 PetscAssertPointer(flg, 3); 9497 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9498 *set = PETSC_TRUE; 9499 *flg = PetscBool3ToBool(A->symmetric); 9500 } else { 9501 *set = PETSC_FALSE; 9502 } 9503 PetscFunctionReturn(PETSC_SUCCESS); 9504 } 9505 9506 /*@ 9507 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9508 9509 Not Collective 9510 9511 Input Parameter: 9512 . A - the matrix to check 9513 9514 Output Parameters: 9515 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9516 - flg - the result (only valid if set is `PETSC_TRUE`) 9517 9518 Level: advanced 9519 9520 Notes: 9521 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9522 9523 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9524 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9525 9526 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9527 @*/ 9528 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9529 { 9530 PetscFunctionBegin; 9531 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9532 PetscAssertPointer(set, 2); 9533 PetscAssertPointer(flg, 3); 9534 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9535 *set = PETSC_TRUE; 9536 *flg = PetscBool3ToBool(A->spd); 9537 } else { 9538 *set = PETSC_FALSE; 9539 } 9540 PetscFunctionReturn(PETSC_SUCCESS); 9541 } 9542 9543 /*@ 9544 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9545 9546 Not Collective 9547 9548 Input Parameter: 9549 . A - the matrix to check 9550 9551 Output Parameters: 9552 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9553 - flg - the result (only valid if set is `PETSC_TRUE`) 9554 9555 Level: advanced 9556 9557 Notes: 9558 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9559 if you want it explicitly checked 9560 9561 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9562 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9563 9564 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9565 @*/ 9566 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9567 { 9568 PetscFunctionBegin; 9569 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9570 PetscAssertPointer(set, 2); 9571 PetscAssertPointer(flg, 3); 9572 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9573 *set = PETSC_TRUE; 9574 *flg = PetscBool3ToBool(A->hermitian); 9575 } else { 9576 *set = PETSC_FALSE; 9577 } 9578 PetscFunctionReturn(PETSC_SUCCESS); 9579 } 9580 9581 /*@ 9582 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9583 9584 Collective 9585 9586 Input Parameter: 9587 . A - the matrix to test 9588 9589 Output Parameter: 9590 . flg - the result 9591 9592 Level: intermediate 9593 9594 Notes: 9595 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9596 9597 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 9598 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9599 9600 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9601 @*/ 9602 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9603 { 9604 PetscFunctionBegin; 9605 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9606 PetscAssertPointer(flg, 2); 9607 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9608 *flg = PetscBool3ToBool(A->structurally_symmetric); 9609 } else { 9610 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9611 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9612 } 9613 PetscFunctionReturn(PETSC_SUCCESS); 9614 } 9615 9616 /*@ 9617 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9618 9619 Not Collective 9620 9621 Input Parameter: 9622 . A - the matrix to check 9623 9624 Output Parameters: 9625 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9626 - flg - the result (only valid if set is PETSC_TRUE) 9627 9628 Level: advanced 9629 9630 Notes: 9631 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 9632 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9633 9634 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9635 9636 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9637 @*/ 9638 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9639 { 9640 PetscFunctionBegin; 9641 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9642 PetscAssertPointer(set, 2); 9643 PetscAssertPointer(flg, 3); 9644 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9645 *set = PETSC_TRUE; 9646 *flg = PetscBool3ToBool(A->structurally_symmetric); 9647 } else { 9648 *set = PETSC_FALSE; 9649 } 9650 PetscFunctionReturn(PETSC_SUCCESS); 9651 } 9652 9653 /*@ 9654 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9655 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9656 9657 Not Collective 9658 9659 Input Parameter: 9660 . mat - the matrix 9661 9662 Output Parameters: 9663 + nstash - the size of the stash 9664 . reallocs - the number of additional mallocs incurred. 9665 . bnstash - the size of the block stash 9666 - breallocs - the number of additional mallocs incurred.in the block stash 9667 9668 Level: advanced 9669 9670 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9671 @*/ 9672 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9673 { 9674 PetscFunctionBegin; 9675 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9676 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9677 PetscFunctionReturn(PETSC_SUCCESS); 9678 } 9679 9680 /*@ 9681 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9682 parallel layout, `PetscLayout` for rows and columns 9683 9684 Collective 9685 9686 Input Parameter: 9687 . mat - the matrix 9688 9689 Output Parameters: 9690 + right - (optional) vector that the matrix can be multiplied against 9691 - left - (optional) vector that the matrix vector product can be stored in 9692 9693 Level: advanced 9694 9695 Notes: 9696 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()`. 9697 9698 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9699 9700 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9701 @*/ 9702 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9703 { 9704 PetscFunctionBegin; 9705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9706 PetscValidType(mat, 1); 9707 if (mat->ops->getvecs) { 9708 PetscUseTypeMethod(mat, getvecs, right, left); 9709 } else { 9710 if (right) { 9711 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9712 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9713 PetscCall(VecSetType(*right, mat->defaultvectype)); 9714 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9715 if (mat->boundtocpu && mat->bindingpropagates) { 9716 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9717 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9718 } 9719 #endif 9720 } 9721 if (left) { 9722 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9723 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9724 PetscCall(VecSetType(*left, mat->defaultvectype)); 9725 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9726 if (mat->boundtocpu && mat->bindingpropagates) { 9727 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9728 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9729 } 9730 #endif 9731 } 9732 } 9733 PetscFunctionReturn(PETSC_SUCCESS); 9734 } 9735 9736 /*@ 9737 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9738 with default values. 9739 9740 Not Collective 9741 9742 Input Parameter: 9743 . info - the `MatFactorInfo` data structure 9744 9745 Level: developer 9746 9747 Notes: 9748 The solvers are generally used through the `KSP` and `PC` objects, for example 9749 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9750 9751 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9752 9753 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9754 @*/ 9755 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9756 { 9757 PetscFunctionBegin; 9758 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9759 PetscFunctionReturn(PETSC_SUCCESS); 9760 } 9761 9762 /*@ 9763 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9764 9765 Collective 9766 9767 Input Parameters: 9768 + mat - the factored matrix 9769 - is - the index set defining the Schur indices (0-based) 9770 9771 Level: advanced 9772 9773 Notes: 9774 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9775 9776 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9777 9778 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9779 9780 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9781 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9782 @*/ 9783 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9784 { 9785 PetscErrorCode (*f)(Mat, IS); 9786 9787 PetscFunctionBegin; 9788 PetscValidType(mat, 1); 9789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9790 PetscValidType(is, 2); 9791 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9792 PetscCheckSameComm(mat, 1, is, 2); 9793 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9794 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9795 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9796 PetscCall(MatDestroy(&mat->schur)); 9797 PetscCall((*f)(mat, is)); 9798 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9799 PetscFunctionReturn(PETSC_SUCCESS); 9800 } 9801 9802 /*@ 9803 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9804 9805 Logically Collective 9806 9807 Input Parameters: 9808 + F - the factored matrix obtained by calling `MatGetFactor()` 9809 . S - location where to return the Schur complement, can be `NULL` 9810 - status - the status of the Schur complement matrix, can be `NULL` 9811 9812 Level: advanced 9813 9814 Notes: 9815 You must call `MatFactorSetSchurIS()` before calling this routine. 9816 9817 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9818 9819 The routine provides a copy of the Schur matrix stored within the solver data structures. 9820 The caller must destroy the object when it is no longer needed. 9821 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9822 9823 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) 9824 9825 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9826 9827 Developer Note: 9828 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9829 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9830 9831 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9832 @*/ 9833 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9834 { 9835 PetscFunctionBegin; 9836 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9837 if (S) PetscAssertPointer(S, 2); 9838 if (status) PetscAssertPointer(status, 3); 9839 if (S) { 9840 PetscErrorCode (*f)(Mat, Mat *); 9841 9842 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9843 if (f) { 9844 PetscCall((*f)(F, S)); 9845 } else { 9846 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9847 } 9848 } 9849 if (status) *status = F->schur_status; 9850 PetscFunctionReturn(PETSC_SUCCESS); 9851 } 9852 9853 /*@ 9854 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9855 9856 Logically Collective 9857 9858 Input Parameters: 9859 + F - the factored matrix obtained by calling `MatGetFactor()` 9860 . S - location where to return the Schur complement, can be `NULL` 9861 - status - the status of the Schur complement matrix, can be `NULL` 9862 9863 Level: advanced 9864 9865 Notes: 9866 You must call `MatFactorSetSchurIS()` before calling this routine. 9867 9868 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9869 9870 The routine returns a the Schur Complement stored within the data structures of the solver. 9871 9872 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9873 9874 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9875 9876 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9877 9878 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9879 9880 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9881 @*/ 9882 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9883 { 9884 PetscFunctionBegin; 9885 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9886 if (S) { 9887 PetscAssertPointer(S, 2); 9888 *S = F->schur; 9889 } 9890 if (status) { 9891 PetscAssertPointer(status, 3); 9892 *status = F->schur_status; 9893 } 9894 PetscFunctionReturn(PETSC_SUCCESS); 9895 } 9896 9897 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9898 { 9899 Mat S = F->schur; 9900 9901 PetscFunctionBegin; 9902 switch (F->schur_status) { 9903 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9904 case MAT_FACTOR_SCHUR_INVERTED: 9905 if (S) { 9906 S->ops->solve = NULL; 9907 S->ops->matsolve = NULL; 9908 S->ops->solvetranspose = NULL; 9909 S->ops->matsolvetranspose = NULL; 9910 S->ops->solveadd = NULL; 9911 S->ops->solvetransposeadd = NULL; 9912 S->factortype = MAT_FACTOR_NONE; 9913 PetscCall(PetscFree(S->solvertype)); 9914 } 9915 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9916 break; 9917 default: 9918 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9919 } 9920 PetscFunctionReturn(PETSC_SUCCESS); 9921 } 9922 9923 /*@ 9924 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9925 9926 Logically Collective 9927 9928 Input Parameters: 9929 + F - the factored matrix obtained by calling `MatGetFactor()` 9930 . S - location where the Schur complement is stored 9931 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9932 9933 Level: advanced 9934 9935 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9936 @*/ 9937 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9938 { 9939 PetscFunctionBegin; 9940 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9941 if (S) { 9942 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9943 *S = NULL; 9944 } 9945 F->schur_status = status; 9946 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9947 PetscFunctionReturn(PETSC_SUCCESS); 9948 } 9949 9950 /*@ 9951 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9952 9953 Logically Collective 9954 9955 Input Parameters: 9956 + F - the factored matrix obtained by calling `MatGetFactor()` 9957 . rhs - location where the right-hand side of the Schur complement system is stored 9958 - sol - location where the solution of the Schur complement system has to be returned 9959 9960 Level: advanced 9961 9962 Notes: 9963 The sizes of the vectors should match the size of the Schur complement 9964 9965 Must be called after `MatFactorSetSchurIS()` 9966 9967 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9968 @*/ 9969 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9970 { 9971 PetscFunctionBegin; 9972 PetscValidType(F, 1); 9973 PetscValidType(rhs, 2); 9974 PetscValidType(sol, 3); 9975 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9976 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9977 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9978 PetscCheckSameComm(F, 1, rhs, 2); 9979 PetscCheckSameComm(F, 1, sol, 3); 9980 PetscCall(MatFactorFactorizeSchurComplement(F)); 9981 switch (F->schur_status) { 9982 case MAT_FACTOR_SCHUR_FACTORED: 9983 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9984 break; 9985 case MAT_FACTOR_SCHUR_INVERTED: 9986 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9987 break; 9988 default: 9989 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9990 } 9991 PetscFunctionReturn(PETSC_SUCCESS); 9992 } 9993 9994 /*@ 9995 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9996 9997 Logically Collective 9998 9999 Input Parameters: 10000 + F - the factored matrix obtained by calling `MatGetFactor()` 10001 . rhs - location where the right-hand side of the Schur complement system is stored 10002 - sol - location where the solution of the Schur complement system has to be returned 10003 10004 Level: advanced 10005 10006 Notes: 10007 The sizes of the vectors should match the size of the Schur complement 10008 10009 Must be called after `MatFactorSetSchurIS()` 10010 10011 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10012 @*/ 10013 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10014 { 10015 PetscFunctionBegin; 10016 PetscValidType(F, 1); 10017 PetscValidType(rhs, 2); 10018 PetscValidType(sol, 3); 10019 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10020 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10021 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10022 PetscCheckSameComm(F, 1, rhs, 2); 10023 PetscCheckSameComm(F, 1, sol, 3); 10024 PetscCall(MatFactorFactorizeSchurComplement(F)); 10025 switch (F->schur_status) { 10026 case MAT_FACTOR_SCHUR_FACTORED: 10027 PetscCall(MatSolve(F->schur, rhs, sol)); 10028 break; 10029 case MAT_FACTOR_SCHUR_INVERTED: 10030 PetscCall(MatMult(F->schur, rhs, sol)); 10031 break; 10032 default: 10033 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10034 } 10035 PetscFunctionReturn(PETSC_SUCCESS); 10036 } 10037 10038 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10039 #if PetscDefined(HAVE_CUDA) 10040 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10041 #endif 10042 10043 /* Schur status updated in the interface */ 10044 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10045 { 10046 Mat S = F->schur; 10047 10048 PetscFunctionBegin; 10049 if (S) { 10050 PetscMPIInt size; 10051 PetscBool isdense, isdensecuda; 10052 10053 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10054 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10055 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10056 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10057 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10058 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10059 if (isdense) { 10060 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10061 } else if (isdensecuda) { 10062 #if defined(PETSC_HAVE_CUDA) 10063 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10064 #endif 10065 } 10066 // HIP?????????????? 10067 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10068 } 10069 PetscFunctionReturn(PETSC_SUCCESS); 10070 } 10071 10072 /*@ 10073 MatFactorInvertSchurComplement - Invert 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 Notes: 10083 Must be called after `MatFactorSetSchurIS()`. 10084 10085 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10086 10087 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10088 @*/ 10089 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10090 { 10091 PetscFunctionBegin; 10092 PetscValidType(F, 1); 10093 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10094 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10095 PetscCall(MatFactorFactorizeSchurComplement(F)); 10096 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10097 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10098 PetscFunctionReturn(PETSC_SUCCESS); 10099 } 10100 10101 /*@ 10102 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10103 10104 Logically Collective 10105 10106 Input Parameter: 10107 . F - the factored matrix obtained by calling `MatGetFactor()` 10108 10109 Level: advanced 10110 10111 Note: 10112 Must be called after `MatFactorSetSchurIS()` 10113 10114 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10115 @*/ 10116 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10117 { 10118 MatFactorInfo info; 10119 10120 PetscFunctionBegin; 10121 PetscValidType(F, 1); 10122 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10123 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10124 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10125 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10126 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10127 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10128 } else { 10129 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10130 } 10131 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10132 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10133 PetscFunctionReturn(PETSC_SUCCESS); 10134 } 10135 10136 /*@ 10137 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10138 10139 Neighbor-wise Collective 10140 10141 Input Parameters: 10142 + A - the matrix 10143 . P - the projection matrix 10144 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10145 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10146 if the result is a dense matrix this is irrelevant 10147 10148 Output Parameter: 10149 . C - the product matrix 10150 10151 Level: intermediate 10152 10153 Notes: 10154 C will be created and must be destroyed by the user with `MatDestroy()`. 10155 10156 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10157 10158 Developer Note: 10159 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10160 10161 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10162 @*/ 10163 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10164 { 10165 PetscFunctionBegin; 10166 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10167 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10168 10169 if (scall == MAT_INITIAL_MATRIX) { 10170 PetscCall(MatProductCreate(A, P, NULL, C)); 10171 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10172 PetscCall(MatProductSetAlgorithm(*C, "default")); 10173 PetscCall(MatProductSetFill(*C, fill)); 10174 10175 (*C)->product->api_user = PETSC_TRUE; 10176 PetscCall(MatProductSetFromOptions(*C)); 10177 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); 10178 PetscCall(MatProductSymbolic(*C)); 10179 } else { /* scall == MAT_REUSE_MATRIX */ 10180 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10181 } 10182 10183 PetscCall(MatProductNumeric(*C)); 10184 (*C)->symmetric = A->symmetric; 10185 (*C)->spd = A->spd; 10186 PetscFunctionReturn(PETSC_SUCCESS); 10187 } 10188 10189 /*@ 10190 MatRARt - Creates the matrix product $C = R * A * R^T$ 10191 10192 Neighbor-wise Collective 10193 10194 Input Parameters: 10195 + A - the matrix 10196 . R - the projection matrix 10197 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10198 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10199 if the result is a dense matrix this is irrelevant 10200 10201 Output Parameter: 10202 . C - the product matrix 10203 10204 Level: intermediate 10205 10206 Notes: 10207 C will be created and must be destroyed by the user with `MatDestroy()`. 10208 10209 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10210 10211 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10212 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10213 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10214 We recommend using MatPtAP(). 10215 10216 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10217 @*/ 10218 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10219 { 10220 PetscFunctionBegin; 10221 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10222 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10223 10224 if (scall == MAT_INITIAL_MATRIX) { 10225 PetscCall(MatProductCreate(A, R, NULL, C)); 10226 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10227 PetscCall(MatProductSetAlgorithm(*C, "default")); 10228 PetscCall(MatProductSetFill(*C, fill)); 10229 10230 (*C)->product->api_user = PETSC_TRUE; 10231 PetscCall(MatProductSetFromOptions(*C)); 10232 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); 10233 PetscCall(MatProductSymbolic(*C)); 10234 } else { /* scall == MAT_REUSE_MATRIX */ 10235 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10236 } 10237 10238 PetscCall(MatProductNumeric(*C)); 10239 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10240 PetscFunctionReturn(PETSC_SUCCESS); 10241 } 10242 10243 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10244 { 10245 PetscBool flg = PETSC_TRUE; 10246 10247 PetscFunctionBegin; 10248 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10249 if (scall == MAT_INITIAL_MATRIX) { 10250 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10251 PetscCall(MatProductCreate(A, B, NULL, C)); 10252 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10253 PetscCall(MatProductSetFill(*C, fill)); 10254 } else { /* scall == MAT_REUSE_MATRIX */ 10255 Mat_Product *product = (*C)->product; 10256 10257 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10258 if (flg && product && product->type != ptype) { 10259 PetscCall(MatProductClear(*C)); 10260 product = NULL; 10261 } 10262 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10263 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10264 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10265 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10266 product = (*C)->product; 10267 product->fill = fill; 10268 product->clear = PETSC_TRUE; 10269 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10270 flg = PETSC_FALSE; 10271 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10272 } 10273 } 10274 if (flg) { 10275 (*C)->product->api_user = PETSC_TRUE; 10276 PetscCall(MatProductSetType(*C, ptype)); 10277 PetscCall(MatProductSetFromOptions(*C)); 10278 PetscCall(MatProductSymbolic(*C)); 10279 } 10280 PetscCall(MatProductNumeric(*C)); 10281 PetscFunctionReturn(PETSC_SUCCESS); 10282 } 10283 10284 /*@ 10285 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10286 10287 Neighbor-wise Collective 10288 10289 Input Parameters: 10290 + A - the left matrix 10291 . B - the right matrix 10292 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10293 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10294 if the result is a dense matrix this is irrelevant 10295 10296 Output Parameter: 10297 . C - the product matrix 10298 10299 Notes: 10300 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10301 10302 `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 10303 call to this function with `MAT_INITIAL_MATRIX`. 10304 10305 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10306 10307 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`, 10308 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10309 10310 Example of Usage: 10311 .vb 10312 MatProductCreate(A,B,NULL,&C); 10313 MatProductSetType(C,MATPRODUCT_AB); 10314 MatProductSymbolic(C); 10315 MatProductNumeric(C); // compute C=A * B 10316 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10317 MatProductNumeric(C); 10318 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10319 MatProductNumeric(C); 10320 .ve 10321 10322 Level: intermediate 10323 10324 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10325 @*/ 10326 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10327 { 10328 PetscFunctionBegin; 10329 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10330 PetscFunctionReturn(PETSC_SUCCESS); 10331 } 10332 10333 /*@ 10334 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10335 10336 Neighbor-wise Collective 10337 10338 Input Parameters: 10339 + A - the left matrix 10340 . B - the right matrix 10341 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10342 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10343 10344 Output Parameter: 10345 . C - the product matrix 10346 10347 Options Database Key: 10348 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10349 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10350 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10351 10352 Level: intermediate 10353 10354 Notes: 10355 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10356 10357 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10358 10359 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10360 actually needed. 10361 10362 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10363 and for pairs of `MATMPIDENSE` matrices. 10364 10365 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10366 10367 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10368 @*/ 10369 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10370 { 10371 PetscFunctionBegin; 10372 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10373 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10374 PetscFunctionReturn(PETSC_SUCCESS); 10375 } 10376 10377 /*@ 10378 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10379 10380 Neighbor-wise Collective 10381 10382 Input Parameters: 10383 + A - the left matrix 10384 . B - the right matrix 10385 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10386 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10387 10388 Output Parameter: 10389 . C - the product matrix 10390 10391 Level: intermediate 10392 10393 Notes: 10394 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10395 10396 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10397 10398 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10399 10400 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10401 actually needed. 10402 10403 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10404 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10405 10406 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10407 @*/ 10408 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10409 { 10410 PetscFunctionBegin; 10411 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10412 PetscFunctionReturn(PETSC_SUCCESS); 10413 } 10414 10415 /*@ 10416 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10417 10418 Neighbor-wise Collective 10419 10420 Input Parameters: 10421 + A - the left matrix 10422 . B - the middle matrix 10423 . C - the right matrix 10424 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10425 - 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 10426 if the result is a dense matrix this is irrelevant 10427 10428 Output Parameter: 10429 . D - the product matrix 10430 10431 Level: intermediate 10432 10433 Notes: 10434 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10435 10436 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10437 10438 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10439 10440 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10441 actually needed. 10442 10443 If you have many matrices with the same non-zero structure to multiply, you 10444 should use `MAT_REUSE_MATRIX` in all calls but the first 10445 10446 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10447 @*/ 10448 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10449 { 10450 PetscFunctionBegin; 10451 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10452 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10453 10454 if (scall == MAT_INITIAL_MATRIX) { 10455 PetscCall(MatProductCreate(A, B, C, D)); 10456 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10457 PetscCall(MatProductSetAlgorithm(*D, "default")); 10458 PetscCall(MatProductSetFill(*D, fill)); 10459 10460 (*D)->product->api_user = PETSC_TRUE; 10461 PetscCall(MatProductSetFromOptions(*D)); 10462 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, 10463 ((PetscObject)C)->type_name); 10464 PetscCall(MatProductSymbolic(*D)); 10465 } else { /* user may change input matrices when REUSE */ 10466 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10467 } 10468 PetscCall(MatProductNumeric(*D)); 10469 PetscFunctionReturn(PETSC_SUCCESS); 10470 } 10471 10472 /*@ 10473 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10474 10475 Collective 10476 10477 Input Parameters: 10478 + mat - the matrix 10479 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10480 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10481 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10482 10483 Output Parameter: 10484 . matredundant - redundant matrix 10485 10486 Level: advanced 10487 10488 Notes: 10489 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10490 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10491 10492 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10493 calling it. 10494 10495 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10496 10497 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10498 @*/ 10499 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10500 { 10501 MPI_Comm comm; 10502 PetscMPIInt size; 10503 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10504 Mat_Redundant *redund = NULL; 10505 PetscSubcomm psubcomm = NULL; 10506 MPI_Comm subcomm_in = subcomm; 10507 Mat *matseq; 10508 IS isrow, iscol; 10509 PetscBool newsubcomm = PETSC_FALSE; 10510 10511 PetscFunctionBegin; 10512 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10513 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10514 PetscAssertPointer(*matredundant, 5); 10515 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10516 } 10517 10518 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10519 if (size == 1 || nsubcomm == 1) { 10520 if (reuse == MAT_INITIAL_MATRIX) { 10521 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10522 } else { 10523 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"); 10524 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10525 } 10526 PetscFunctionReturn(PETSC_SUCCESS); 10527 } 10528 10529 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10530 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10531 MatCheckPreallocated(mat, 1); 10532 10533 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10534 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10535 /* create psubcomm, then get subcomm */ 10536 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10537 PetscCallMPI(MPI_Comm_size(comm, &size)); 10538 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10539 10540 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10541 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10542 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10543 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10544 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10545 newsubcomm = PETSC_TRUE; 10546 PetscCall(PetscSubcommDestroy(&psubcomm)); 10547 } 10548 10549 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10550 if (reuse == MAT_INITIAL_MATRIX) { 10551 mloc_sub = PETSC_DECIDE; 10552 nloc_sub = PETSC_DECIDE; 10553 if (bs < 1) { 10554 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10555 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10556 } else { 10557 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10558 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10559 } 10560 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10561 rstart = rend - mloc_sub; 10562 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10563 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10564 PetscCall(ISSetIdentity(iscol)); 10565 } else { /* reuse == MAT_REUSE_MATRIX */ 10566 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"); 10567 /* retrieve subcomm */ 10568 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10569 redund = (*matredundant)->redundant; 10570 isrow = redund->isrow; 10571 iscol = redund->iscol; 10572 matseq = redund->matseq; 10573 } 10574 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10575 10576 /* get matredundant over subcomm */ 10577 if (reuse == MAT_INITIAL_MATRIX) { 10578 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10579 10580 /* create a supporting struct and attach it to C for reuse */ 10581 PetscCall(PetscNew(&redund)); 10582 (*matredundant)->redundant = redund; 10583 redund->isrow = isrow; 10584 redund->iscol = iscol; 10585 redund->matseq = matseq; 10586 if (newsubcomm) { 10587 redund->subcomm = subcomm; 10588 } else { 10589 redund->subcomm = MPI_COMM_NULL; 10590 } 10591 } else { 10592 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10593 } 10594 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10595 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10596 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10597 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10598 } 10599 #endif 10600 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10601 PetscFunctionReturn(PETSC_SUCCESS); 10602 } 10603 10604 /*@C 10605 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10606 a given `Mat`. Each submatrix can span multiple procs. 10607 10608 Collective 10609 10610 Input Parameters: 10611 + mat - the matrix 10612 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10613 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10614 10615 Output Parameter: 10616 . subMat - parallel sub-matrices each spanning a given `subcomm` 10617 10618 Level: advanced 10619 10620 Notes: 10621 The submatrix partition across processors is dictated by `subComm` a 10622 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10623 is not restricted to be grouped with consecutive original MPI processes. 10624 10625 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10626 map directly to the layout of the original matrix [wrt the local 10627 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10628 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10629 the `subMat`. However the offDiagMat looses some columns - and this is 10630 reconstructed with `MatSetValues()` 10631 10632 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10633 10634 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10635 @*/ 10636 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10637 { 10638 PetscMPIInt commsize, subCommSize; 10639 10640 PetscFunctionBegin; 10641 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10642 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10643 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10644 10645 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"); 10646 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10647 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10648 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10649 PetscFunctionReturn(PETSC_SUCCESS); 10650 } 10651 10652 /*@ 10653 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10654 10655 Not Collective 10656 10657 Input Parameters: 10658 + mat - matrix to extract local submatrix from 10659 . isrow - local row indices for submatrix 10660 - iscol - local column indices for submatrix 10661 10662 Output Parameter: 10663 . submat - the submatrix 10664 10665 Level: intermediate 10666 10667 Notes: 10668 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10669 10670 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10671 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10672 10673 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10674 `MatSetValuesBlockedLocal()` will also be implemented. 10675 10676 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10677 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10678 10679 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10680 @*/ 10681 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10682 { 10683 PetscFunctionBegin; 10684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10685 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10686 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10687 PetscCheckSameComm(isrow, 2, iscol, 3); 10688 PetscAssertPointer(submat, 4); 10689 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10690 10691 if (mat->ops->getlocalsubmatrix) { 10692 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10693 } else { 10694 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10695 } 10696 PetscFunctionReturn(PETSC_SUCCESS); 10697 } 10698 10699 /*@ 10700 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10701 10702 Not Collective 10703 10704 Input Parameters: 10705 + mat - matrix to extract local submatrix from 10706 . isrow - local row indices for submatrix 10707 . iscol - local column indices for submatrix 10708 - submat - the submatrix 10709 10710 Level: intermediate 10711 10712 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10713 @*/ 10714 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10715 { 10716 PetscFunctionBegin; 10717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10718 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10719 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10720 PetscCheckSameComm(isrow, 2, iscol, 3); 10721 PetscAssertPointer(submat, 4); 10722 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10723 10724 if (mat->ops->restorelocalsubmatrix) { 10725 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10726 } else { 10727 PetscCall(MatDestroy(submat)); 10728 } 10729 *submat = NULL; 10730 PetscFunctionReturn(PETSC_SUCCESS); 10731 } 10732 10733 /*@ 10734 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10735 10736 Collective 10737 10738 Input Parameter: 10739 . mat - the matrix 10740 10741 Output Parameter: 10742 . is - if any rows have zero diagonals this contains the list of them 10743 10744 Level: developer 10745 10746 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10747 @*/ 10748 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10749 { 10750 PetscFunctionBegin; 10751 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10752 PetscValidType(mat, 1); 10753 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10754 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10755 10756 if (!mat->ops->findzerodiagonals) { 10757 Vec diag; 10758 const PetscScalar *a; 10759 PetscInt *rows; 10760 PetscInt rStart, rEnd, r, nrow = 0; 10761 10762 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10763 PetscCall(MatGetDiagonal(mat, diag)); 10764 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10765 PetscCall(VecGetArrayRead(diag, &a)); 10766 for (r = 0; r < rEnd - rStart; ++r) 10767 if (a[r] == 0.0) ++nrow; 10768 PetscCall(PetscMalloc1(nrow, &rows)); 10769 nrow = 0; 10770 for (r = 0; r < rEnd - rStart; ++r) 10771 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10772 PetscCall(VecRestoreArrayRead(diag, &a)); 10773 PetscCall(VecDestroy(&diag)); 10774 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10775 } else { 10776 PetscUseTypeMethod(mat, findzerodiagonals, is); 10777 } 10778 PetscFunctionReturn(PETSC_SUCCESS); 10779 } 10780 10781 /*@ 10782 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10783 10784 Collective 10785 10786 Input Parameter: 10787 . mat - the matrix 10788 10789 Output Parameter: 10790 . is - contains the list of rows with off block diagonal entries 10791 10792 Level: developer 10793 10794 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10795 @*/ 10796 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10797 { 10798 PetscFunctionBegin; 10799 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10800 PetscValidType(mat, 1); 10801 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10802 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10803 10804 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10805 PetscFunctionReturn(PETSC_SUCCESS); 10806 } 10807 10808 /*@C 10809 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10810 10811 Collective; No Fortran Support 10812 10813 Input Parameter: 10814 . mat - the matrix 10815 10816 Output Parameter: 10817 . values - the block inverses in column major order (FORTRAN-like) 10818 10819 Level: advanced 10820 10821 Notes: 10822 The size of the blocks is determined by the block size of the matrix. 10823 10824 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10825 10826 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10827 10828 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10829 @*/ 10830 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10831 { 10832 PetscFunctionBegin; 10833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10834 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10835 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10836 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10837 PetscFunctionReturn(PETSC_SUCCESS); 10838 } 10839 10840 /*@ 10841 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10842 10843 Collective; No Fortran Support 10844 10845 Input Parameters: 10846 + mat - the matrix 10847 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10848 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10849 10850 Output Parameter: 10851 . values - the block inverses in column major order (FORTRAN-like) 10852 10853 Level: advanced 10854 10855 Notes: 10856 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10857 10858 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10859 10860 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10861 @*/ 10862 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10863 { 10864 PetscFunctionBegin; 10865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10866 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10867 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10868 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10869 PetscFunctionReturn(PETSC_SUCCESS); 10870 } 10871 10872 /*@ 10873 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10874 10875 Collective 10876 10877 Input Parameters: 10878 + A - the matrix 10879 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10880 10881 Level: advanced 10882 10883 Note: 10884 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10885 10886 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10887 @*/ 10888 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10889 { 10890 const PetscScalar *vals; 10891 PetscInt *dnnz; 10892 PetscInt m, rstart, rend, bs, i, j; 10893 10894 PetscFunctionBegin; 10895 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10896 PetscCall(MatGetBlockSize(A, &bs)); 10897 PetscCall(MatGetLocalSize(A, &m, NULL)); 10898 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10899 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10900 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10901 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10902 PetscCall(PetscFree(dnnz)); 10903 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10904 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10905 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10906 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10907 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10908 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10909 PetscFunctionReturn(PETSC_SUCCESS); 10910 } 10911 10912 /*@ 10913 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10914 via `MatTransposeColoringCreate()`. 10915 10916 Collective 10917 10918 Input Parameter: 10919 . c - coloring context 10920 10921 Level: intermediate 10922 10923 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10924 @*/ 10925 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10926 { 10927 MatTransposeColoring matcolor = *c; 10928 10929 PetscFunctionBegin; 10930 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10931 if (--((PetscObject)matcolor)->refct > 0) { 10932 matcolor = NULL; 10933 PetscFunctionReturn(PETSC_SUCCESS); 10934 } 10935 10936 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10937 PetscCall(PetscFree(matcolor->rows)); 10938 PetscCall(PetscFree(matcolor->den2sp)); 10939 PetscCall(PetscFree(matcolor->colorforcol)); 10940 PetscCall(PetscFree(matcolor->columns)); 10941 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10942 PetscCall(PetscHeaderDestroy(c)); 10943 PetscFunctionReturn(PETSC_SUCCESS); 10944 } 10945 10946 /*@ 10947 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10948 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10949 `MatTransposeColoring` to sparse `B`. 10950 10951 Collective 10952 10953 Input Parameters: 10954 + coloring - coloring context created with `MatTransposeColoringCreate()` 10955 - B - sparse matrix 10956 10957 Output Parameter: 10958 . Btdense - dense matrix $B^T$ 10959 10960 Level: developer 10961 10962 Note: 10963 These are used internally for some implementations of `MatRARt()` 10964 10965 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10966 @*/ 10967 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10968 { 10969 PetscFunctionBegin; 10970 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10971 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10972 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10973 10974 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10975 PetscFunctionReturn(PETSC_SUCCESS); 10976 } 10977 10978 /*@ 10979 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10980 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10981 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10982 $C_{sp}$ from $C_{den}$. 10983 10984 Collective 10985 10986 Input Parameters: 10987 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10988 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10989 10990 Output Parameter: 10991 . Csp - sparse matrix 10992 10993 Level: developer 10994 10995 Note: 10996 These are used internally for some implementations of `MatRARt()` 10997 10998 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10999 @*/ 11000 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11001 { 11002 PetscFunctionBegin; 11003 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11004 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11005 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11006 11007 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11008 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11009 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11010 PetscFunctionReturn(PETSC_SUCCESS); 11011 } 11012 11013 /*@ 11014 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11015 11016 Collective 11017 11018 Input Parameters: 11019 + mat - the matrix product C 11020 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11021 11022 Output Parameter: 11023 . color - the new coloring context 11024 11025 Level: intermediate 11026 11027 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11028 `MatTransColoringApplyDenToSp()` 11029 @*/ 11030 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11031 { 11032 MatTransposeColoring c; 11033 MPI_Comm comm; 11034 11035 PetscFunctionBegin; 11036 PetscAssertPointer(color, 3); 11037 11038 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11039 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11040 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11041 c->ctype = iscoloring->ctype; 11042 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11043 *color = c; 11044 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11045 PetscFunctionReturn(PETSC_SUCCESS); 11046 } 11047 11048 /*@ 11049 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11050 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11051 11052 Not Collective 11053 11054 Input Parameter: 11055 . mat - the matrix 11056 11057 Output Parameter: 11058 . state - the current state 11059 11060 Level: intermediate 11061 11062 Notes: 11063 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11064 different matrices 11065 11066 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11067 11068 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11069 11070 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11071 @*/ 11072 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11073 { 11074 PetscFunctionBegin; 11075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11076 *state = mat->nonzerostate; 11077 PetscFunctionReturn(PETSC_SUCCESS); 11078 } 11079 11080 /*@ 11081 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11082 matrices from each processor 11083 11084 Collective 11085 11086 Input Parameters: 11087 + comm - the communicators the parallel matrix will live on 11088 . seqmat - the input sequential matrices 11089 . n - number of local columns (or `PETSC_DECIDE`) 11090 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11091 11092 Output Parameter: 11093 . mpimat - the parallel matrix generated 11094 11095 Level: developer 11096 11097 Note: 11098 The number of columns of the matrix in EACH processor MUST be the same. 11099 11100 .seealso: [](ch_matrices), `Mat` 11101 @*/ 11102 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11103 { 11104 PetscMPIInt size; 11105 11106 PetscFunctionBegin; 11107 PetscCallMPI(MPI_Comm_size(comm, &size)); 11108 if (size == 1) { 11109 if (reuse == MAT_INITIAL_MATRIX) { 11110 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11111 } else { 11112 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11113 } 11114 PetscFunctionReturn(PETSC_SUCCESS); 11115 } 11116 11117 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"); 11118 11119 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11120 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11121 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11122 PetscFunctionReturn(PETSC_SUCCESS); 11123 } 11124 11125 /*@ 11126 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11127 11128 Collective 11129 11130 Input Parameters: 11131 + A - the matrix to create subdomains from 11132 - N - requested number of subdomains 11133 11134 Output Parameters: 11135 + n - number of subdomains resulting on this MPI process 11136 - iss - `IS` list with indices of subdomains on this MPI process 11137 11138 Level: advanced 11139 11140 Note: 11141 The number of subdomains must be smaller than the communicator size 11142 11143 .seealso: [](ch_matrices), `Mat`, `IS` 11144 @*/ 11145 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11146 { 11147 MPI_Comm comm, subcomm; 11148 PetscMPIInt size, rank, color; 11149 PetscInt rstart, rend, k; 11150 11151 PetscFunctionBegin; 11152 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11153 PetscCallMPI(MPI_Comm_size(comm, &size)); 11154 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11155 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); 11156 *n = 1; 11157 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11158 color = rank / k; 11159 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11160 PetscCall(PetscMalloc1(1, iss)); 11161 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11162 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11163 PetscCallMPI(MPI_Comm_free(&subcomm)); 11164 PetscFunctionReturn(PETSC_SUCCESS); 11165 } 11166 11167 /*@ 11168 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11169 11170 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11171 If they are not the same, uses `MatMatMatMult()`. 11172 11173 Once the coarse grid problem is constructed, correct for interpolation operators 11174 that are not of full rank, which can legitimately happen in the case of non-nested 11175 geometric multigrid. 11176 11177 Input Parameters: 11178 + restrct - restriction operator 11179 . dA - fine grid matrix 11180 . interpolate - interpolation operator 11181 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11182 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11183 11184 Output Parameter: 11185 . A - the Galerkin coarse matrix 11186 11187 Options Database Key: 11188 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11189 11190 Level: developer 11191 11192 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11193 @*/ 11194 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11195 { 11196 IS zerorows; 11197 Vec diag; 11198 11199 PetscFunctionBegin; 11200 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11201 /* Construct the coarse grid matrix */ 11202 if (interpolate == restrct) { 11203 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11204 } else { 11205 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11206 } 11207 11208 /* If the interpolation matrix is not of full rank, A will have zero rows. 11209 This can legitimately happen in the case of non-nested geometric multigrid. 11210 In that event, we set the rows of the matrix to the rows of the identity, 11211 ignoring the equations (as the RHS will also be zero). */ 11212 11213 PetscCall(MatFindZeroRows(*A, &zerorows)); 11214 11215 if (zerorows != NULL) { /* if there are any zero rows */ 11216 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11217 PetscCall(MatGetDiagonal(*A, diag)); 11218 PetscCall(VecISSet(diag, zerorows, 1.0)); 11219 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11220 PetscCall(VecDestroy(&diag)); 11221 PetscCall(ISDestroy(&zerorows)); 11222 } 11223 PetscFunctionReturn(PETSC_SUCCESS); 11224 } 11225 11226 /*@C 11227 MatSetOperation - Allows user to set a matrix operation for any matrix type 11228 11229 Logically Collective 11230 11231 Input Parameters: 11232 + mat - the matrix 11233 . op - the name of the operation 11234 - f - the function that provides the operation 11235 11236 Level: developer 11237 11238 Example Usage: 11239 .vb 11240 extern PetscErrorCode usermult(Mat, Vec, Vec); 11241 11242 PetscCall(MatCreateXXX(comm, ..., &A)); 11243 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11244 .ve 11245 11246 Notes: 11247 See the file `include/petscmat.h` for a complete list of matrix 11248 operations, which all have the form MATOP_<OPERATION>, where 11249 <OPERATION> is the name (in all capital letters) of the 11250 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11251 11252 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11253 sequence as the usual matrix interface routines, since they 11254 are intended to be accessed via the usual matrix interface 11255 routines, e.g., 11256 .vb 11257 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11258 .ve 11259 11260 In particular each function MUST return `PETSC_SUCCESS` on success and 11261 nonzero on failure. 11262 11263 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11264 11265 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11266 @*/ 11267 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11268 { 11269 PetscFunctionBegin; 11270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11271 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11272 (((void (**)(void))mat->ops)[op]) = f; 11273 PetscFunctionReturn(PETSC_SUCCESS); 11274 } 11275 11276 /*@C 11277 MatGetOperation - Gets a matrix operation for any matrix type. 11278 11279 Not Collective 11280 11281 Input Parameters: 11282 + mat - the matrix 11283 - op - the name of the operation 11284 11285 Output Parameter: 11286 . f - the function that provides the operation 11287 11288 Level: developer 11289 11290 Example Usage: 11291 .vb 11292 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11293 11294 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11295 .ve 11296 11297 Notes: 11298 See the file include/petscmat.h for a complete list of matrix 11299 operations, which all have the form MATOP_<OPERATION>, where 11300 <OPERATION> is the name (in all capital letters) of the 11301 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11302 11303 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11304 11305 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11306 @*/ 11307 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11308 { 11309 PetscFunctionBegin; 11310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11311 *f = (((void (**)(void))mat->ops)[op]); 11312 PetscFunctionReturn(PETSC_SUCCESS); 11313 } 11314 11315 /*@ 11316 MatHasOperation - Determines whether the given matrix supports the particular operation. 11317 11318 Not Collective 11319 11320 Input Parameters: 11321 + mat - the matrix 11322 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11323 11324 Output Parameter: 11325 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11326 11327 Level: advanced 11328 11329 Note: 11330 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11331 11332 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11333 @*/ 11334 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11335 { 11336 PetscFunctionBegin; 11337 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11338 PetscAssertPointer(has, 3); 11339 if (mat->ops->hasoperation) { 11340 PetscUseTypeMethod(mat, hasoperation, op, has); 11341 } else { 11342 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11343 else { 11344 *has = PETSC_FALSE; 11345 if (op == MATOP_CREATE_SUBMATRIX) { 11346 PetscMPIInt size; 11347 11348 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11349 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11350 } 11351 } 11352 } 11353 PetscFunctionReturn(PETSC_SUCCESS); 11354 } 11355 11356 /*@ 11357 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11358 11359 Collective 11360 11361 Input Parameter: 11362 . mat - the matrix 11363 11364 Output Parameter: 11365 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11366 11367 Level: beginner 11368 11369 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11370 @*/ 11371 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11372 { 11373 PetscFunctionBegin; 11374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11375 PetscValidType(mat, 1); 11376 PetscAssertPointer(cong, 2); 11377 if (!mat->rmap || !mat->cmap) { 11378 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11379 PetscFunctionReturn(PETSC_SUCCESS); 11380 } 11381 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11382 PetscCall(PetscLayoutSetUp(mat->rmap)); 11383 PetscCall(PetscLayoutSetUp(mat->cmap)); 11384 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11385 if (*cong) mat->congruentlayouts = 1; 11386 else mat->congruentlayouts = 0; 11387 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11388 PetscFunctionReturn(PETSC_SUCCESS); 11389 } 11390 11391 PetscErrorCode MatSetInf(Mat A) 11392 { 11393 PetscFunctionBegin; 11394 PetscUseTypeMethod(A, setinf); 11395 PetscFunctionReturn(PETSC_SUCCESS); 11396 } 11397 11398 /*@ 11399 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 11400 and possibly removes small values from the graph structure. 11401 11402 Collective 11403 11404 Input Parameters: 11405 + A - the matrix 11406 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11407 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11408 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11409 . num_idx - size of 'index' array 11410 - index - array of block indices to use for graph strength of connection weight 11411 11412 Output Parameter: 11413 . graph - the resulting graph 11414 11415 Level: advanced 11416 11417 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11418 @*/ 11419 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11420 { 11421 PetscFunctionBegin; 11422 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11423 PetscValidType(A, 1); 11424 PetscValidLogicalCollectiveBool(A, scale, 3); 11425 PetscAssertPointer(graph, 7); 11426 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11427 PetscFunctionReturn(PETSC_SUCCESS); 11428 } 11429 11430 /*@ 11431 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11432 meaning the same memory is used for the matrix, and no new memory is allocated. 11433 11434 Collective 11435 11436 Input Parameters: 11437 + A - the matrix 11438 - 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 11439 11440 Level: intermediate 11441 11442 Developer Note: 11443 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11444 of the arrays in the data structure are unneeded. 11445 11446 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11447 @*/ 11448 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11449 { 11450 PetscFunctionBegin; 11451 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11452 PetscUseTypeMethod(A, eliminatezeros, keep); 11453 PetscFunctionReturn(PETSC_SUCCESS); 11454 } 11455