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; 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 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 269 @*/ 270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 271 { 272 PetscFunctionBegin; 273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 274 PetscValidType(mat, 1); 275 PetscAssertPointer(keptrows, 2); 276 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 277 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 278 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 279 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 280 PetscFunctionReturn(PETSC_SUCCESS); 281 } 282 283 /*@ 284 MatFindZeroRows - Locate all rows that are completely zero in the matrix 285 286 Input Parameter: 287 . mat - the matrix 288 289 Output Parameter: 290 . zerorows - the rows that are completely zero 291 292 Level: intermediate 293 294 Note: 295 `zerorows` is set to `NULL` if no rows are zero. 296 297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 298 @*/ 299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 300 { 301 IS keptrows; 302 PetscInt m, n; 303 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 306 PetscValidType(mat, 1); 307 PetscAssertPointer(zerorows, 2); 308 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 309 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 310 In keeping with this convention, we set zerorows to NULL if there are no zero 311 rows. */ 312 if (keptrows == NULL) { 313 *zerorows = NULL; 314 } else { 315 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 316 PetscCall(ISComplement(keptrows, m, n, zerorows)); 317 PetscCall(ISDestroy(&keptrows)); 318 } 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 324 325 Not Collective 326 327 Input Parameter: 328 . A - the matrix 329 330 Output Parameter: 331 . a - the diagonal part (which is a SEQUENTIAL matrix) 332 333 Level: advanced 334 335 Notes: 336 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 337 338 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 339 340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 341 @*/ 342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 343 { 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 346 PetscValidType(A, 1); 347 PetscAssertPointer(a, 2); 348 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 349 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 350 else { 351 PetscMPIInt size; 352 353 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 354 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 355 *a = A; 356 } 357 PetscFunctionReturn(PETSC_SUCCESS); 358 } 359 360 /*@ 361 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 362 363 Collective 364 365 Input Parameter: 366 . mat - the matrix 367 368 Output Parameter: 369 . trace - the sum of the diagonal entries 370 371 Level: advanced 372 373 .seealso: [](ch_matrices), `Mat` 374 @*/ 375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 376 { 377 Vec diag; 378 379 PetscFunctionBegin; 380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 381 PetscAssertPointer(trace, 2); 382 PetscCall(MatCreateVecs(mat, &diag, NULL)); 383 PetscCall(MatGetDiagonal(mat, diag)); 384 PetscCall(VecSum(diag, trace)); 385 PetscCall(VecDestroy(&diag)); 386 PetscFunctionReturn(PETSC_SUCCESS); 387 } 388 389 /*@ 390 MatRealPart - Zeros out the imaginary part of the matrix 391 392 Logically Collective 393 394 Input Parameter: 395 . mat - the matrix 396 397 Level: advanced 398 399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 400 @*/ 401 PetscErrorCode MatRealPart(Mat mat) 402 { 403 PetscFunctionBegin; 404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 405 PetscValidType(mat, 1); 406 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 407 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 408 MatCheckPreallocated(mat, 1); 409 PetscUseTypeMethod(mat, realpart); 410 PetscFunctionReturn(PETSC_SUCCESS); 411 } 412 413 /*@C 414 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 415 416 Collective 417 418 Input Parameter: 419 . mat - the matrix 420 421 Output Parameters: 422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 423 - ghosts - the global indices of the ghost points 424 425 Level: advanced 426 427 Note: 428 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 429 430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 431 @*/ 432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 433 { 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 436 PetscValidType(mat, 1); 437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 439 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 440 else { 441 if (nghosts) *nghosts = 0; 442 if (ghosts) *ghosts = NULL; 443 } 444 PetscFunctionReturn(PETSC_SUCCESS); 445 } 446 447 /*@ 448 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 449 450 Logically Collective 451 452 Input Parameter: 453 . mat - the matrix 454 455 Level: advanced 456 457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 458 @*/ 459 PetscErrorCode MatImaginaryPart(Mat mat) 460 { 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 463 PetscValidType(mat, 1); 464 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 465 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 466 MatCheckPreallocated(mat, 1); 467 PetscUseTypeMethod(mat, imaginarypart); 468 PetscFunctionReturn(PETSC_SUCCESS); 469 } 470 471 /*@ 472 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 473 474 Not Collective 475 476 Input Parameter: 477 . mat - the matrix 478 479 Output Parameters: 480 + missing - is any diagonal entry missing 481 - dd - first diagonal entry that is missing (optional) on this process 482 483 Level: advanced 484 485 Note: 486 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 487 488 .seealso: [](ch_matrices), `Mat` 489 @*/ 490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 491 { 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 494 PetscValidType(mat, 1); 495 PetscAssertPointer(missing, 2); 496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 498 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 503 /*@C 504 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 505 for each row that you get to ensure that your application does 506 not bleed memory. 507 508 Not Collective 509 510 Input Parameters: 511 + mat - the matrix 512 - row - the row to get 513 514 Output Parameters: 515 + ncols - if not `NULL`, the number of nonzeros in `row` 516 . cols - if not `NULL`, the column numbers 517 - vals - if not `NULL`, the numerical values 518 519 Level: advanced 520 521 Notes: 522 This routine is provided for people who need to have direct access 523 to the structure of a matrix. We hope that we provide enough 524 high-level matrix routines that few users will need it. 525 526 `MatGetRow()` always returns 0-based column indices, regardless of 527 whether the internal representation is 0-based (default) or 1-based. 528 529 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 530 not wish to extract these quantities. 531 532 The user can only examine the values extracted with `MatGetRow()`; 533 the values CANNOT be altered. To change the matrix entries, one 534 must use `MatSetValues()`. 535 536 You can only have one call to `MatGetRow()` outstanding for a particular 537 matrix at a time, per processor. `MatGetRow()` can only obtain rows 538 associated with the given processor, it cannot get rows from the 539 other processors; for that we suggest using `MatCreateSubMatrices()`, then 540 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 541 is in the global number of rows. 542 543 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 544 545 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 546 547 Fortran Note: 548 The calling sequence is 549 .vb 550 MatGetRow(matrix,row,ncols,cols,values,ierr) 551 Mat matrix (input) 552 integer row (input) 553 integer ncols (output) 554 integer cols(maxcols) (output) 555 double precision (or double complex) values(maxcols) output 556 .ve 557 where maxcols >= maximum nonzeros in any row of the matrix. 558 559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 560 @*/ 561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 562 { 563 PetscInt incols; 564 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 567 PetscValidType(mat, 1); 568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 570 MatCheckPreallocated(mat, 1); 571 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 572 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 573 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 574 if (ncols) *ncols = incols; 575 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 576 PetscFunctionReturn(PETSC_SUCCESS); 577 } 578 579 /*@ 580 MatConjugate - replaces the matrix values with their complex conjugates 581 582 Logically Collective 583 584 Input Parameter: 585 . mat - the matrix 586 587 Level: advanced 588 589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 590 @*/ 591 PetscErrorCode MatConjugate(Mat mat) 592 { 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 596 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 597 PetscUseTypeMethod(mat, conjugate); 598 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 599 } 600 PetscFunctionReturn(PETSC_SUCCESS); 601 } 602 603 /*@C 604 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 605 606 Not Collective 607 608 Input Parameters: 609 + mat - the matrix 610 . row - the row to get 611 . ncols - the number of nonzeros 612 . cols - the columns of the nonzeros 613 - vals - if nonzero the column values 614 615 Level: advanced 616 617 Notes: 618 This routine should be called after you have finished examining the entries. 619 620 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 621 us of the array after it has been restored. If you pass `NULL`, it will 622 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 623 624 Fortran Notes: 625 The calling sequence is 626 .vb 627 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 628 Mat matrix (input) 629 integer row (input) 630 integer ncols (output) 631 integer cols(maxcols) (output) 632 double precision (or double complex) values(maxcols) output 633 .ve 634 Where maxcols >= maximum nonzeros in any row of the matrix. 635 636 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 637 before another call to `MatGetRow()` can be made. 638 639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 640 @*/ 641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 642 { 643 PetscFunctionBegin; 644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 645 if (ncols) PetscAssertPointer(ncols, 3); 646 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 647 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 648 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 649 if (ncols) *ncols = 0; 650 if (cols) *cols = NULL; 651 if (vals) *vals = NULL; 652 PetscFunctionReturn(PETSC_SUCCESS); 653 } 654 655 /*@ 656 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 657 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 658 659 Not Collective 660 661 Input Parameter: 662 . mat - the matrix 663 664 Level: advanced 665 666 Note: 667 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. 668 669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 670 @*/ 671 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 672 { 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 675 PetscValidType(mat, 1); 676 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 677 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 678 MatCheckPreallocated(mat, 1); 679 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 680 PetscUseTypeMethod(mat, getrowuppertriangular); 681 PetscFunctionReturn(PETSC_SUCCESS); 682 } 683 684 /*@ 685 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 686 687 Not Collective 688 689 Input Parameter: 690 . mat - the matrix 691 692 Level: advanced 693 694 Note: 695 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 696 697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 698 @*/ 699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 700 { 701 PetscFunctionBegin; 702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 703 PetscValidType(mat, 1); 704 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 705 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 706 MatCheckPreallocated(mat, 1); 707 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 708 PetscUseTypeMethod(mat, restorerowuppertriangular); 709 PetscFunctionReturn(PETSC_SUCCESS); 710 } 711 712 /*@C 713 MatSetOptionsPrefix - Sets the prefix used for searching for all 714 `Mat` options in the database. 715 716 Logically Collective 717 718 Input Parameters: 719 + A - the matrix 720 - prefix - the prefix to prepend to all option names 721 722 Level: advanced 723 724 Notes: 725 A hyphen (-) must NOT be given at the beginning of the prefix name. 726 The first character of all runtime options is AUTOMATICALLY the hyphen. 727 728 This is NOT used for options for the factorization of the matrix. Normally the 729 prefix is automatically passed in from the PC calling the factorization. To set 730 it directly use `MatSetOptionsPrefixFactor()` 731 732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 733 @*/ 734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 735 { 736 PetscFunctionBegin; 737 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 738 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 739 PetscFunctionReturn(PETSC_SUCCESS); 740 } 741 742 /*@C 743 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 744 for matrices created with `MatGetFactor()` 745 746 Logically Collective 747 748 Input Parameters: 749 + A - the matrix 750 - prefix - the prefix to prepend to all option names for the factored matrix 751 752 Level: developer 753 754 Notes: 755 A hyphen (-) must NOT be given at the beginning of the prefix name. 756 The first character of all runtime options is AUTOMATICALLY the hyphen. 757 758 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 759 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 760 761 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 762 @*/ 763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 764 { 765 PetscFunctionBegin; 766 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 767 if (prefix) { 768 PetscAssertPointer(prefix, 2); 769 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 770 if (prefix != A->factorprefix) { 771 PetscCall(PetscFree(A->factorprefix)); 772 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 773 } 774 } else PetscCall(PetscFree(A->factorprefix)); 775 PetscFunctionReturn(PETSC_SUCCESS); 776 } 777 778 /*@C 779 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 780 for matrices created with `MatGetFactor()` 781 782 Logically Collective 783 784 Input Parameters: 785 + A - the matrix 786 - prefix - the prefix to prepend to all option names for the factored matrix 787 788 Level: developer 789 790 Notes: 791 A hyphen (-) must NOT be given at the beginning of the prefix name. 792 The first character of all runtime options is AUTOMATICALLY the hyphen. 793 794 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 795 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 796 797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 798 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 799 `MatSetOptionsPrefix()` 800 @*/ 801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 802 { 803 size_t len1, len2, new_len; 804 805 PetscFunctionBegin; 806 PetscValidHeader(A, 1); 807 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 808 if (!A->factorprefix) { 809 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 810 PetscFunctionReturn(PETSC_SUCCESS); 811 } 812 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 813 814 PetscCall(PetscStrlen(A->factorprefix, &len1)); 815 PetscCall(PetscStrlen(prefix, &len2)); 816 new_len = len1 + len2 + 1; 817 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 818 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 819 PetscFunctionReturn(PETSC_SUCCESS); 820 } 821 822 /*@C 823 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 824 matrix options in the database. 825 826 Logically Collective 827 828 Input Parameters: 829 + A - the matrix 830 - prefix - the prefix to prepend to all option names 831 832 Level: advanced 833 834 Note: 835 A hyphen (-) must NOT be given at the beginning of the prefix name. 836 The first character of all runtime options is AUTOMATICALLY the hyphen. 837 838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 839 @*/ 840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 844 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 845 PetscFunctionReturn(PETSC_SUCCESS); 846 } 847 848 /*@C 849 MatGetOptionsPrefix - Gets the prefix used for searching for all 850 matrix options in the database. 851 852 Not Collective 853 854 Input Parameter: 855 . A - the matrix 856 857 Output Parameter: 858 . prefix - pointer to the prefix string used 859 860 Level: advanced 861 862 Fortran Note: 863 The user should pass in a string `prefix` of 864 sufficient length to hold the prefix. 865 866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 867 @*/ 868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 869 { 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 872 PetscAssertPointer(prefix, 2); 873 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 874 PetscFunctionReturn(PETSC_SUCCESS); 875 } 876 877 /*@ 878 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 879 880 Collective 881 882 Input Parameter: 883 . A - the matrix 884 885 Level: beginner 886 887 Notes: 888 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 889 890 Users can reset the preallocation to access the original memory. 891 892 Currently only supported for `MATAIJ` matrices. 893 894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 895 @*/ 896 PetscErrorCode MatResetPreallocation(Mat A) 897 { 898 PetscFunctionBegin; 899 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 900 PetscValidType(A, 1); 901 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()"); 902 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 903 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 904 PetscFunctionReturn(PETSC_SUCCESS); 905 } 906 907 /*@ 908 MatSetUp - Sets up the internal matrix data structures for later use. 909 910 Collective 911 912 Input Parameter: 913 . A - the matrix 914 915 Level: intermediate 916 917 Notes: 918 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 919 setting values in the matrix. 920 921 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 922 923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 924 @*/ 925 PetscErrorCode MatSetUp(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 if (!((PetscObject)A)->type_name) { 930 PetscMPIInt size; 931 932 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 933 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 934 } 935 if (!A->preallocated) PetscTryTypeMethod(A, setup); 936 PetscCall(PetscLayoutSetUp(A->rmap)); 937 PetscCall(PetscLayoutSetUp(A->cmap)); 938 A->preallocated = PETSC_TRUE; 939 PetscFunctionReturn(PETSC_SUCCESS); 940 } 941 942 #if defined(PETSC_HAVE_SAWS) 943 #include <petscviewersaws.h> 944 #endif 945 946 /* 947 If threadsafety is on extraneous matrices may be printed 948 949 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 950 */ 951 #if !defined(PETSC_HAVE_THREADSAFETY) 952 static PetscInt insidematview = 0; 953 #endif 954 955 /*@C 956 MatViewFromOptions - View properties of the matrix based on options set in the options database 957 958 Collective 959 960 Input Parameters: 961 + A - the matrix 962 . obj - optional additional object that provides the options prefix to use 963 - name - command line option 964 965 Options Database Key: 966 . -mat_view [viewertype]:... - the viewer and its options 967 968 Level: intermediate 969 970 Note: 971 .vb 972 If no value is provided ascii:stdout is used 973 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 974 for example ascii::ascii_info prints just the information about the object not all details 975 unless :append is given filename opens in write mode, overwriting what was already there 976 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 977 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 978 socket[:port] defaults to the standard output port 979 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 980 .ve 981 982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 983 @*/ 984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 985 { 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 988 #if !defined(PETSC_HAVE_THREADSAFETY) 989 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 990 #endif 991 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 992 PetscFunctionReturn(PETSC_SUCCESS); 993 } 994 995 /*@C 996 MatView - display information about a matrix in a variety ways 997 998 Collective on viewer 999 1000 Input Parameters: 1001 + mat - the matrix 1002 - viewer - visualization context 1003 1004 Options Database Keys: 1005 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1006 . -mat_view ::ascii_info_detail - Prints more detailed info 1007 . -mat_view - Prints matrix in ASCII format 1008 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1009 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1010 . -display <name> - Sets display name (default is host) 1011 . -draw_pause <sec> - Sets number of seconds to pause after display 1012 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1013 . -viewer_socket_machine <machine> - - 1014 . -viewer_socket_port <port> - - 1015 . -mat_view binary - save matrix to file in binary format 1016 - -viewer_binary_filename <name> - - 1017 1018 Level: beginner 1019 1020 Notes: 1021 The available visualization contexts include 1022 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1023 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1024 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1025 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1026 1027 The user can open alternative visualization contexts with 1028 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1029 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1030 specified file; corresponding input uses `MatLoad()` 1031 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1032 an X window display 1033 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1034 Currently only the `MATSEQDENSE` and `MATAIJ` 1035 matrix types support the Socket viewer. 1036 1037 The user can call `PetscViewerPushFormat()` to specify the output 1038 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1039 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1040 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1041 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1042 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1043 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1044 format common among all matrix types 1045 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1046 format (which is in many cases the same as the default) 1047 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1048 size and structure (not the matrix entries) 1049 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1050 the matrix structure 1051 1052 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1053 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1054 1055 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1056 1057 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1058 viewer is used. 1059 1060 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1061 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1062 1063 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1064 and then use the following mouse functions. 1065 .vb 1066 left mouse: zoom in 1067 middle mouse: zoom out 1068 right mouse: continue with the simulation 1069 .ve 1070 1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1072 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1073 @*/ 1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1075 { 1076 PetscInt rows, cols, rbs, cbs; 1077 PetscBool isascii, isstring, issaws; 1078 PetscViewerFormat format; 1079 PetscMPIInt size; 1080 1081 PetscFunctionBegin; 1082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1083 PetscValidType(mat, 1); 1084 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1085 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1086 1087 PetscCall(PetscViewerGetFormat(viewer, &format)); 1088 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1089 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1090 1091 #if !defined(PETSC_HAVE_THREADSAFETY) 1092 insidematview++; 1093 #endif 1094 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1097 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"); 1098 1099 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1100 if (isascii) { 1101 if (!mat->preallocated) { 1102 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1103 #if !defined(PETSC_HAVE_THREADSAFETY) 1104 insidematview--; 1105 #endif 1106 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1107 PetscFunctionReturn(PETSC_SUCCESS); 1108 } 1109 if (!mat->assembled) { 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1111 #if !defined(PETSC_HAVE_THREADSAFETY) 1112 insidematview--; 1113 #endif 1114 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1115 PetscFunctionReturn(PETSC_SUCCESS); 1116 } 1117 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1118 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1119 MatNullSpace nullsp, transnullsp; 1120 1121 PetscCall(PetscViewerASCIIPushTab(viewer)); 1122 PetscCall(MatGetSize(mat, &rows, &cols)); 1123 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1124 if (rbs != 1 || cbs != 1) { 1125 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" : "")); 1126 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1127 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1128 if (mat->factortype) { 1129 MatSolverType solver; 1130 PetscCall(MatFactorGetSolverType(mat, &solver)); 1131 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1132 } 1133 if (mat->ops->getinfo) { 1134 MatInfo info; 1135 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1136 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1137 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1138 } 1139 PetscCall(MatGetNullSpace(mat, &nullsp)); 1140 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1141 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1142 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1143 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1144 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1145 PetscCall(PetscViewerASCIIPushTab(viewer)); 1146 PetscCall(MatProductView(mat, viewer)); 1147 PetscCall(PetscViewerASCIIPopTab(viewer)); 1148 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1149 IS tmp; 1150 1151 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1152 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1153 PetscCall(PetscViewerASCIIPushTab(viewer)); 1154 PetscCall(ISView(tmp, viewer)); 1155 PetscCall(PetscViewerASCIIPopTab(viewer)); 1156 PetscCall(ISDestroy(&tmp)); 1157 } 1158 } 1159 } else if (issaws) { 1160 #if defined(PETSC_HAVE_SAWS) 1161 PetscMPIInt rank; 1162 1163 PetscCall(PetscObjectName((PetscObject)mat)); 1164 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1165 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1166 #endif 1167 } else if (isstring) { 1168 const char *type; 1169 PetscCall(MatGetType(mat, &type)); 1170 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1171 PetscTryTypeMethod(mat, view, viewer); 1172 } 1173 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1174 PetscCall(PetscViewerASCIIPushTab(viewer)); 1175 PetscUseTypeMethod(mat, viewnative, viewer); 1176 PetscCall(PetscViewerASCIIPopTab(viewer)); 1177 } else if (mat->ops->view) { 1178 PetscCall(PetscViewerASCIIPushTab(viewer)); 1179 PetscUseTypeMethod(mat, view, viewer); 1180 PetscCall(PetscViewerASCIIPopTab(viewer)); 1181 } 1182 if (isascii) { 1183 PetscCall(PetscViewerGetFormat(viewer, &format)); 1184 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1185 } 1186 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1187 #if !defined(PETSC_HAVE_THREADSAFETY) 1188 insidematview--; 1189 #endif 1190 PetscFunctionReturn(PETSC_SUCCESS); 1191 } 1192 1193 #if defined(PETSC_USE_DEBUG) 1194 #include <../src/sys/totalview/tv_data_display.h> 1195 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1196 { 1197 TV_add_row("Local rows", "int", &mat->rmap->n); 1198 TV_add_row("Local columns", "int", &mat->cmap->n); 1199 TV_add_row("Global rows", "int", &mat->rmap->N); 1200 TV_add_row("Global columns", "int", &mat->cmap->N); 1201 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1202 return TV_format_OK; 1203 } 1204 #endif 1205 1206 /*@C 1207 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1208 with `MatView()`. The matrix format is determined from the options database. 1209 Generates a parallel MPI matrix if the communicator has more than one 1210 processor. The default matrix type is `MATAIJ`. 1211 1212 Collective 1213 1214 Input Parameters: 1215 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1216 or some related function before a call to `MatLoad()` 1217 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1218 1219 Options Database Key: 1220 . -matload_block_size <bs> - set block size 1221 1222 Level: beginner 1223 1224 Notes: 1225 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1226 `Mat` before calling this routine if you wish to set it from the options database. 1227 1228 `MatLoad()` automatically loads into the options database any options 1229 given in the file filename.info where filename is the name of the file 1230 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1231 file will be ignored if you use the -viewer_binary_skip_info option. 1232 1233 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1234 sets the default matrix type AIJ and sets the local and global sizes. 1235 If type and/or size is already set, then the same are used. 1236 1237 In parallel, each processor can load a subset of rows (or the 1238 entire matrix). This routine is especially useful when a large 1239 matrix is stored on disk and only part of it is desired on each 1240 processor. For example, a parallel solver may access only some of 1241 the rows from each processor. The algorithm used here reads 1242 relatively small blocks of data rather than reading the entire 1243 matrix and then subsetting it. 1244 1245 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1246 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1247 or the sequence like 1248 .vb 1249 `PetscViewer` v; 1250 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1251 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1252 `PetscViewerSetFromOptions`(v); 1253 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1254 `PetscViewerFileSetName`(v,"datafile"); 1255 .ve 1256 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1257 $ -viewer_type {binary, hdf5} 1258 1259 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1260 and src/mat/tutorials/ex10.c with the second approach. 1261 1262 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1263 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1264 Multiple objects, both matrices and vectors, can be stored within the same file. 1265 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1266 1267 Most users should not need to know the details of the binary storage 1268 format, since `MatLoad()` and `MatView()` completely hide these details. 1269 But for anyone who is interested, the standard binary matrix storage 1270 format is 1271 1272 .vb 1273 PetscInt MAT_FILE_CLASSID 1274 PetscInt number of rows 1275 PetscInt number of columns 1276 PetscInt total number of nonzeros 1277 PetscInt *number nonzeros in each row 1278 PetscInt *column indices of all nonzeros (starting index is zero) 1279 PetscScalar *values of all nonzeros 1280 .ve 1281 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1282 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 1283 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1284 1285 PETSc automatically does the byte swapping for 1286 machines that store the bytes reversed. Thus if you write your own binary 1287 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1288 and `PetscBinaryWrite()` to see how this may be done. 1289 1290 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1291 Each processor's chunk is loaded independently by its owning MPI process. 1292 Multiple objects, both matrices and vectors, can be stored within the same file. 1293 They are looked up by their PetscObject name. 1294 1295 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1296 by default the same structure and naming of the AIJ arrays and column count 1297 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1298 $ save example.mat A b -v7.3 1299 can be directly read by this routine (see Reference 1 for details). 1300 1301 Depending on your MATLAB version, this format might be a default, 1302 otherwise you can set it as default in Preferences. 1303 1304 Unless -nocompression flag is used to save the file in MATLAB, 1305 PETSc must be configured with ZLIB package. 1306 1307 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1308 1309 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1310 1311 Corresponding `MatView()` is not yet implemented. 1312 1313 The loaded matrix is actually a transpose of the original one in MATLAB, 1314 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1315 With this format, matrix is automatically transposed by PETSc, 1316 unless the matrix is marked as SPD or symmetric 1317 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1318 1319 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1320 1321 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1322 @*/ 1323 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1324 { 1325 PetscBool flg; 1326 1327 PetscFunctionBegin; 1328 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1329 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1330 1331 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1332 1333 flg = PETSC_FALSE; 1334 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1335 if (flg) { 1336 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1337 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1338 } 1339 flg = PETSC_FALSE; 1340 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1341 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1342 1343 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1344 PetscUseTypeMethod(mat, load, viewer); 1345 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1346 PetscFunctionReturn(PETSC_SUCCESS); 1347 } 1348 1349 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1350 { 1351 Mat_Redundant *redund = *redundant; 1352 1353 PetscFunctionBegin; 1354 if (redund) { 1355 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1356 PetscCall(ISDestroy(&redund->isrow)); 1357 PetscCall(ISDestroy(&redund->iscol)); 1358 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1359 } else { 1360 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1361 PetscCall(PetscFree(redund->sbuf_j)); 1362 PetscCall(PetscFree(redund->sbuf_a)); 1363 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1364 PetscCall(PetscFree(redund->rbuf_j[i])); 1365 PetscCall(PetscFree(redund->rbuf_a[i])); 1366 } 1367 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1368 } 1369 1370 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1371 PetscCall(PetscFree(redund)); 1372 } 1373 PetscFunctionReturn(PETSC_SUCCESS); 1374 } 1375 1376 /*@C 1377 MatDestroy - Frees space taken by a matrix. 1378 1379 Collective 1380 1381 Input Parameter: 1382 . A - the matrix 1383 1384 Level: beginner 1385 1386 Developer Note: 1387 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1388 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1389 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1390 if changes are needed here. 1391 1392 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1393 @*/ 1394 PetscErrorCode MatDestroy(Mat *A) 1395 { 1396 PetscFunctionBegin; 1397 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1398 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1399 if (--((PetscObject)*A)->refct > 0) { 1400 *A = NULL; 1401 PetscFunctionReturn(PETSC_SUCCESS); 1402 } 1403 1404 /* if memory was published with SAWs then destroy it */ 1405 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1406 PetscTryTypeMethod(*A, destroy); 1407 1408 PetscCall(PetscFree((*A)->factorprefix)); 1409 PetscCall(PetscFree((*A)->defaultvectype)); 1410 PetscCall(PetscFree((*A)->defaultrandtype)); 1411 PetscCall(PetscFree((*A)->bsizes)); 1412 PetscCall(PetscFree((*A)->solvertype)); 1413 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1414 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1415 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1416 PetscCall(MatProductClear(*A)); 1417 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1418 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1419 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1420 PetscCall(MatDestroy(&(*A)->schur)); 1421 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1422 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1423 PetscCall(PetscHeaderDestroy(A)); 1424 PetscFunctionReturn(PETSC_SUCCESS); 1425 } 1426 1427 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1428 /*@C 1429 MatSetValues - Inserts or adds a block of values into a matrix. 1430 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1431 MUST be called after all calls to `MatSetValues()` have been completed. 1432 1433 Not Collective 1434 1435 Input Parameters: 1436 + mat - the matrix 1437 . v - a logically two-dimensional array of values 1438 . m - the number of rows 1439 . idxm - the global indices of the rows 1440 . n - the number of columns 1441 . idxn - the global indices of the columns 1442 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1443 1444 Level: beginner 1445 1446 Notes: 1447 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1448 1449 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1450 options cannot be mixed without intervening calls to the assembly 1451 routines. 1452 1453 `MatSetValues()` uses 0-based row and column numbers in Fortran 1454 as well as in C. 1455 1456 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1457 simply ignored. This allows easily inserting element stiffness matrices 1458 with homogeneous Dirichlet boundary conditions that you don't want represented 1459 in the matrix. 1460 1461 Efficiency Alert: 1462 The routine `MatSetValuesBlocked()` may offer much better efficiency 1463 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1464 1465 Developer Note: 1466 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1467 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1468 1469 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1470 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1471 @*/ 1472 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1473 { 1474 PetscFunctionBeginHot; 1475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1476 PetscValidType(mat, 1); 1477 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1478 PetscAssertPointer(idxm, 3); 1479 PetscAssertPointer(idxn, 5); 1480 MatCheckPreallocated(mat, 1); 1481 1482 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1483 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1484 1485 if (PetscDefined(USE_DEBUG)) { 1486 PetscInt i, j; 1487 1488 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1489 if (v) { 1490 for (i = 0; i < m; i++) { 1491 for (j = 0; j < n; j++) { 1492 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1493 #if defined(PETSC_USE_COMPLEX) 1494 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]); 1495 #else 1496 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]); 1497 #endif 1498 } 1499 } 1500 } 1501 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); 1502 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); 1503 } 1504 1505 if (mat->assembled) { 1506 mat->was_assembled = PETSC_TRUE; 1507 mat->assembled = PETSC_FALSE; 1508 } 1509 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1510 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1511 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1512 PetscFunctionReturn(PETSC_SUCCESS); 1513 } 1514 1515 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1516 /*@C 1517 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1518 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1519 MUST be called after all calls to `MatSetValues()` have been completed. 1520 1521 Not Collective 1522 1523 Input Parameters: 1524 + mat - the matrix 1525 . v - a logically two-dimensional array of values 1526 . ism - the rows to provide 1527 . isn - the columns to provide 1528 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1529 1530 Level: beginner 1531 1532 Notes: 1533 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1534 1535 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1536 options cannot be mixed without intervening calls to the assembly 1537 routines. 1538 1539 `MatSetValues()` uses 0-based row and column numbers in Fortran 1540 as well as in C. 1541 1542 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1543 simply ignored. This allows easily inserting element stiffness matrices 1544 with homogeneous Dirichlet boundary conditions that you don't want represented 1545 in the matrix. 1546 1547 Efficiency Alert: 1548 The routine `MatSetValuesBlocked()` may offer much better efficiency 1549 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1550 1551 This is currently not optimized for any particular `ISType` 1552 1553 Developer Note: 1554 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1555 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1556 1557 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1559 @*/ 1560 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1561 { 1562 PetscInt m, n; 1563 const PetscInt *rows, *cols; 1564 1565 PetscFunctionBeginHot; 1566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1567 PetscCall(ISGetIndices(ism, &rows)); 1568 PetscCall(ISGetIndices(isn, &cols)); 1569 PetscCall(ISGetLocalSize(ism, &m)); 1570 PetscCall(ISGetLocalSize(isn, &n)); 1571 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1572 PetscCall(ISRestoreIndices(ism, &rows)); 1573 PetscCall(ISRestoreIndices(isn, &cols)); 1574 PetscFunctionReturn(PETSC_SUCCESS); 1575 } 1576 1577 /*@ 1578 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1579 values into a matrix 1580 1581 Not Collective 1582 1583 Input Parameters: 1584 + mat - the matrix 1585 . row - the (block) row to set 1586 - v - a logically two-dimensional array of values 1587 1588 Level: intermediate 1589 1590 Notes: 1591 The values, `v`, are column-oriented (for the block version) and sorted 1592 1593 All the nonzero values in `row` must be provided 1594 1595 The matrix must have previously had its column indices set, likely by having been assembled. 1596 1597 `row` must belong to this MPI process 1598 1599 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1600 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1601 @*/ 1602 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1603 { 1604 PetscInt globalrow; 1605 1606 PetscFunctionBegin; 1607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1608 PetscValidType(mat, 1); 1609 PetscAssertPointer(v, 3); 1610 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1611 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1612 PetscFunctionReturn(PETSC_SUCCESS); 1613 } 1614 1615 /*@ 1616 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1617 values into a matrix 1618 1619 Not Collective 1620 1621 Input Parameters: 1622 + mat - the matrix 1623 . row - the (block) row to set 1624 - 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 1625 1626 Level: advanced 1627 1628 Notes: 1629 The values, `v`, are column-oriented for the block version. 1630 1631 All the nonzeros in `row` must be provided 1632 1633 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1634 1635 `row` must belong to this process 1636 1637 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1638 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1639 @*/ 1640 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1641 { 1642 PetscFunctionBeginHot; 1643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1644 PetscValidType(mat, 1); 1645 MatCheckPreallocated(mat, 1); 1646 PetscAssertPointer(v, 3); 1647 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1648 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1649 mat->insertmode = INSERT_VALUES; 1650 1651 if (mat->assembled) { 1652 mat->was_assembled = PETSC_TRUE; 1653 mat->assembled = PETSC_FALSE; 1654 } 1655 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1656 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1657 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1658 PetscFunctionReturn(PETSC_SUCCESS); 1659 } 1660 1661 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1662 /*@ 1663 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1664 Using structured grid indexing 1665 1666 Not Collective 1667 1668 Input Parameters: 1669 + mat - the matrix 1670 . m - number of rows being entered 1671 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1672 . n - number of columns being entered 1673 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1674 . v - a logically two-dimensional array of values 1675 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1676 1677 Level: beginner 1678 1679 Notes: 1680 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1681 1682 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1683 options cannot be mixed without intervening calls to the assembly 1684 routines. 1685 1686 The grid coordinates are across the entire grid, not just the local portion 1687 1688 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1689 as well as in C. 1690 1691 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1692 1693 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1694 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1695 1696 The columns and rows in the stencil passed in MUST be contained within the 1697 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1698 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1699 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1700 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1701 1702 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1703 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1704 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1705 `DM_BOUNDARY_PERIODIC` boundary type. 1706 1707 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 1708 a single value per point) you can skip filling those indices. 1709 1710 Inspired by the structured grid interface to the HYPRE package 1711 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1712 1713 Efficiency Alert: 1714 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1715 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1716 1717 Fortran Note: 1718 `idxm` and `idxn` should be declared as 1719 $ MatStencil idxm(4,m),idxn(4,n) 1720 and the values inserted using 1721 .vb 1722 idxm(MatStencil_i,1) = i 1723 idxm(MatStencil_j,1) = j 1724 idxm(MatStencil_k,1) = k 1725 idxm(MatStencil_c,1) = c 1726 etc 1727 .ve 1728 1729 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1730 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1731 @*/ 1732 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1733 { 1734 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1735 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1736 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1737 1738 PetscFunctionBegin; 1739 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1741 PetscValidType(mat, 1); 1742 PetscAssertPointer(idxm, 3); 1743 PetscAssertPointer(idxn, 5); 1744 1745 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1746 jdxm = buf; 1747 jdxn = buf + m; 1748 } else { 1749 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1750 jdxm = bufm; 1751 jdxn = bufn; 1752 } 1753 for (i = 0; i < m; i++) { 1754 for (j = 0; j < 3 - sdim; j++) dxm++; 1755 tmp = *dxm++ - starts[0]; 1756 for (j = 0; j < dim - 1; j++) { 1757 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1758 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1759 } 1760 if (mat->stencil.noc) dxm++; 1761 jdxm[i] = tmp; 1762 } 1763 for (i = 0; i < n; i++) { 1764 for (j = 0; j < 3 - sdim; j++) dxn++; 1765 tmp = *dxn++ - starts[0]; 1766 for (j = 0; j < dim - 1; j++) { 1767 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1768 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1769 } 1770 if (mat->stencil.noc) dxn++; 1771 jdxn[i] = tmp; 1772 } 1773 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1774 PetscCall(PetscFree2(bufm, bufn)); 1775 PetscFunctionReturn(PETSC_SUCCESS); 1776 } 1777 1778 /*@ 1779 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1780 Using structured grid indexing 1781 1782 Not Collective 1783 1784 Input Parameters: 1785 + mat - the matrix 1786 . m - number of rows being entered 1787 . idxm - grid coordinates for matrix rows being entered 1788 . n - number of columns being entered 1789 . idxn - grid coordinates for matrix columns being entered 1790 . v - a logically two-dimensional array of values 1791 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1792 1793 Level: beginner 1794 1795 Notes: 1796 By default the values, `v`, are row-oriented and unsorted. 1797 See `MatSetOption()` for other options. 1798 1799 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1800 options cannot be mixed without intervening calls to the assembly 1801 routines. 1802 1803 The grid coordinates are across the entire grid, not just the local portion 1804 1805 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1806 as well as in C. 1807 1808 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1809 1810 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1811 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1812 1813 The columns and rows in the stencil passed in MUST be contained within the 1814 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1815 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1816 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1817 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1818 1819 Negative indices may be passed in idxm and idxn, these rows and columns are 1820 simply ignored. This allows easily inserting element stiffness matrices 1821 with homogeneous Dirichlet boundary conditions that you don't want represented 1822 in the matrix. 1823 1824 Inspired by the structured grid interface to the HYPRE package 1825 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1826 1827 Fortran Note: 1828 `idxm` and `idxn` should be declared as 1829 $ MatStencil idxm(4,m),idxn(4,n) 1830 and the values inserted using 1831 .vb 1832 idxm(MatStencil_i,1) = i 1833 idxm(MatStencil_j,1) = j 1834 idxm(MatStencil_k,1) = k 1835 etc 1836 .ve 1837 1838 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1839 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1840 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1841 @*/ 1842 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1843 { 1844 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1845 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1846 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1847 1848 PetscFunctionBegin; 1849 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1850 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1851 PetscValidType(mat, 1); 1852 PetscAssertPointer(idxm, 3); 1853 PetscAssertPointer(idxn, 5); 1854 PetscAssertPointer(v, 6); 1855 1856 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1857 jdxm = buf; 1858 jdxn = buf + m; 1859 } else { 1860 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1861 jdxm = bufm; 1862 jdxn = bufn; 1863 } 1864 for (i = 0; i < m; i++) { 1865 for (j = 0; j < 3 - sdim; j++) dxm++; 1866 tmp = *dxm++ - starts[0]; 1867 for (j = 0; j < sdim - 1; j++) { 1868 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1869 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1870 } 1871 dxm++; 1872 jdxm[i] = tmp; 1873 } 1874 for (i = 0; i < n; i++) { 1875 for (j = 0; j < 3 - sdim; j++) dxn++; 1876 tmp = *dxn++ - starts[0]; 1877 for (j = 0; j < sdim - 1; j++) { 1878 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1879 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1880 } 1881 dxn++; 1882 jdxn[i] = tmp; 1883 } 1884 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1885 PetscCall(PetscFree2(bufm, bufn)); 1886 PetscFunctionReturn(PETSC_SUCCESS); 1887 } 1888 1889 /*@ 1890 MatSetStencil - Sets the grid information for setting values into a matrix via 1891 `MatSetValuesStencil()` 1892 1893 Not Collective 1894 1895 Input Parameters: 1896 + mat - the matrix 1897 . dim - dimension of the grid 1, 2, or 3 1898 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1899 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1900 - dof - number of degrees of freedom per node 1901 1902 Level: beginner 1903 1904 Notes: 1905 Inspired by the structured grid interface to the HYPRE package 1906 (www.llnl.gov/CASC/hyper) 1907 1908 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1909 user. 1910 1911 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1912 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1913 @*/ 1914 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1915 { 1916 PetscFunctionBegin; 1917 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1918 PetscAssertPointer(dims, 3); 1919 PetscAssertPointer(starts, 4); 1920 1921 mat->stencil.dim = dim + (dof > 1); 1922 for (PetscInt i = 0; i < dim; i++) { 1923 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1924 mat->stencil.starts[i] = starts[dim - i - 1]; 1925 } 1926 mat->stencil.dims[dim] = dof; 1927 mat->stencil.starts[dim] = 0; 1928 mat->stencil.noc = (PetscBool)(dof == 1); 1929 PetscFunctionReturn(PETSC_SUCCESS); 1930 } 1931 1932 /*@C 1933 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1934 1935 Not Collective 1936 1937 Input Parameters: 1938 + mat - the matrix 1939 . v - a logically two-dimensional array of values 1940 . m - the number of block rows 1941 . idxm - the global block indices 1942 . n - the number of block columns 1943 . idxn - the global block indices 1944 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1945 1946 Level: intermediate 1947 1948 Notes: 1949 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1950 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1951 1952 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1953 NOT the total number of rows/columns; for example, if the block size is 2 and 1954 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1955 The values in `idxm` would be 1 2; that is the first index for each block divided by 1956 the block size. 1957 1958 You must call `MatSetBlockSize()` when constructing this matrix (before 1959 preallocating it). 1960 1961 By default the values, `v`, are row-oriented, so the layout of 1962 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1963 1964 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1965 options cannot be mixed without intervening calls to the assembly 1966 routines. 1967 1968 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1969 as well as in C. 1970 1971 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1972 simply ignored. This allows easily inserting element stiffness matrices 1973 with homogeneous Dirichlet boundary conditions that you don't want represented 1974 in the matrix. 1975 1976 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1977 internal searching must be done to determine where to place the 1978 data in the matrix storage space. By instead inserting blocks of 1979 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1980 reduced. 1981 1982 Example: 1983 .vb 1984 Suppose m=n=2 and block size(bs) = 2 The array is 1985 1986 1 2 | 3 4 1987 5 6 | 7 8 1988 - - - | - - - 1989 9 10 | 11 12 1990 13 14 | 15 16 1991 1992 v[] should be passed in like 1993 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1994 1995 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1996 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1997 .ve 1998 1999 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2000 @*/ 2001 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2002 { 2003 PetscFunctionBeginHot; 2004 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2005 PetscValidType(mat, 1); 2006 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2007 PetscAssertPointer(idxm, 3); 2008 PetscAssertPointer(idxn, 5); 2009 MatCheckPreallocated(mat, 1); 2010 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2011 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2012 if (PetscDefined(USE_DEBUG)) { 2013 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2014 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2015 } 2016 if (PetscDefined(USE_DEBUG)) { 2017 PetscInt rbs, cbs, M, N, i; 2018 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2019 PetscCall(MatGetSize(mat, &M, &N)); 2020 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 2021 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 2022 } 2023 if (mat->assembled) { 2024 mat->was_assembled = PETSC_TRUE; 2025 mat->assembled = PETSC_FALSE; 2026 } 2027 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2028 if (mat->ops->setvaluesblocked) { 2029 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2030 } else { 2031 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2032 PetscInt i, j, bs, cbs; 2033 2034 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2035 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2036 iidxm = buf; 2037 iidxn = buf + m * bs; 2038 } else { 2039 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2040 iidxm = bufr; 2041 iidxn = bufc; 2042 } 2043 for (i = 0; i < m; i++) { 2044 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2045 } 2046 if (m != n || bs != cbs || idxm != idxn) { 2047 for (i = 0; i < n; i++) { 2048 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2049 } 2050 } else iidxn = iidxm; 2051 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2052 PetscCall(PetscFree2(bufr, bufc)); 2053 } 2054 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2055 PetscFunctionReturn(PETSC_SUCCESS); 2056 } 2057 2058 /*@C 2059 MatGetValues - Gets a block of local values from a matrix. 2060 2061 Not Collective; can only return values that are owned by the give process 2062 2063 Input Parameters: 2064 + mat - the matrix 2065 . v - a logically two-dimensional array for storing the values 2066 . m - the number of rows 2067 . idxm - the global indices of the rows 2068 . n - the number of columns 2069 - idxn - the global indices of the columns 2070 2071 Level: advanced 2072 2073 Notes: 2074 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2075 The values, `v`, are then returned in a row-oriented format, 2076 analogous to that used by default in `MatSetValues()`. 2077 2078 `MatGetValues()` uses 0-based row and column numbers in 2079 Fortran as well as in C. 2080 2081 `MatGetValues()` requires that the matrix has been assembled 2082 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2083 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2084 without intermediate matrix assembly. 2085 2086 Negative row or column indices will be ignored and those locations in `v` will be 2087 left unchanged. 2088 2089 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2090 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2091 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2092 2093 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2094 @*/ 2095 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2096 { 2097 PetscFunctionBegin; 2098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2099 PetscValidType(mat, 1); 2100 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2101 PetscAssertPointer(idxm, 3); 2102 PetscAssertPointer(idxn, 5); 2103 PetscAssertPointer(v, 6); 2104 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2105 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2106 MatCheckPreallocated(mat, 1); 2107 2108 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2109 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2110 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2111 PetscFunctionReturn(PETSC_SUCCESS); 2112 } 2113 2114 /*@C 2115 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2116 defined previously by `MatSetLocalToGlobalMapping()` 2117 2118 Not Collective 2119 2120 Input Parameters: 2121 + mat - the matrix 2122 . nrow - number of rows 2123 . irow - the row local indices 2124 . ncol - number of columns 2125 - icol - the column local indices 2126 2127 Output Parameter: 2128 . y - a logically two-dimensional array of values 2129 2130 Level: advanced 2131 2132 Notes: 2133 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2134 2135 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, 2136 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2137 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2138 with `MatSetLocalToGlobalMapping()`. 2139 2140 Developer Note: 2141 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2142 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2143 2144 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2145 `MatSetValuesLocal()`, `MatGetValues()` 2146 @*/ 2147 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2148 { 2149 PetscFunctionBeginHot; 2150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2151 PetscValidType(mat, 1); 2152 MatCheckPreallocated(mat, 1); 2153 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2154 PetscAssertPointer(irow, 3); 2155 PetscAssertPointer(icol, 5); 2156 if (PetscDefined(USE_DEBUG)) { 2157 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2158 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2159 } 2160 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2161 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2162 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2163 else { 2164 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2165 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2166 irowm = buf; 2167 icolm = buf + nrow; 2168 } else { 2169 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2170 irowm = bufr; 2171 icolm = bufc; 2172 } 2173 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2174 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2175 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2176 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2177 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2178 PetscCall(PetscFree2(bufr, bufc)); 2179 } 2180 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2181 PetscFunctionReturn(PETSC_SUCCESS); 2182 } 2183 2184 /*@ 2185 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2186 the same size. Currently, this can only be called once and creates the given matrix. 2187 2188 Not Collective 2189 2190 Input Parameters: 2191 + mat - the matrix 2192 . nb - the number of blocks 2193 . bs - the number of rows (and columns) in each block 2194 . rows - a concatenation of the rows for each block 2195 - v - a concatenation of logically two-dimensional arrays of values 2196 2197 Level: advanced 2198 2199 Notes: 2200 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2201 2202 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2203 2204 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2205 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2206 @*/ 2207 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2208 { 2209 PetscFunctionBegin; 2210 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2211 PetscValidType(mat, 1); 2212 PetscAssertPointer(rows, 4); 2213 PetscAssertPointer(v, 5); 2214 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2215 2216 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2217 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2218 else { 2219 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2220 } 2221 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2222 PetscFunctionReturn(PETSC_SUCCESS); 2223 } 2224 2225 /*@ 2226 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2227 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2228 using a local (per-processor) numbering. 2229 2230 Not Collective 2231 2232 Input Parameters: 2233 + x - the matrix 2234 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2235 - cmapping - column mapping 2236 2237 Level: intermediate 2238 2239 Note: 2240 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2241 2242 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2243 @*/ 2244 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2245 { 2246 PetscFunctionBegin; 2247 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2248 PetscValidType(x, 1); 2249 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2250 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2251 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2252 else { 2253 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2254 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2255 } 2256 PetscFunctionReturn(PETSC_SUCCESS); 2257 } 2258 2259 /*@ 2260 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2261 2262 Not Collective 2263 2264 Input Parameter: 2265 . A - the matrix 2266 2267 Output Parameters: 2268 + rmapping - row mapping 2269 - cmapping - column mapping 2270 2271 Level: advanced 2272 2273 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2274 @*/ 2275 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2276 { 2277 PetscFunctionBegin; 2278 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2279 PetscValidType(A, 1); 2280 if (rmapping) { 2281 PetscAssertPointer(rmapping, 2); 2282 *rmapping = A->rmap->mapping; 2283 } 2284 if (cmapping) { 2285 PetscAssertPointer(cmapping, 3); 2286 *cmapping = A->cmap->mapping; 2287 } 2288 PetscFunctionReturn(PETSC_SUCCESS); 2289 } 2290 2291 /*@ 2292 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2293 2294 Logically Collective 2295 2296 Input Parameters: 2297 + A - the matrix 2298 . rmap - row layout 2299 - cmap - column layout 2300 2301 Level: advanced 2302 2303 Note: 2304 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2305 2306 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2307 @*/ 2308 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2309 { 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2312 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2313 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2314 PetscFunctionReturn(PETSC_SUCCESS); 2315 } 2316 2317 /*@ 2318 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2319 2320 Not Collective 2321 2322 Input Parameter: 2323 . A - the matrix 2324 2325 Output Parameters: 2326 + rmap - row layout 2327 - cmap - column layout 2328 2329 Level: advanced 2330 2331 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2332 @*/ 2333 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2334 { 2335 PetscFunctionBegin; 2336 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2337 PetscValidType(A, 1); 2338 if (rmap) { 2339 PetscAssertPointer(rmap, 2); 2340 *rmap = A->rmap; 2341 } 2342 if (cmap) { 2343 PetscAssertPointer(cmap, 3); 2344 *cmap = A->cmap; 2345 } 2346 PetscFunctionReturn(PETSC_SUCCESS); 2347 } 2348 2349 /*@C 2350 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2351 using a local numbering of the rows and columns. 2352 2353 Not Collective 2354 2355 Input Parameters: 2356 + mat - the matrix 2357 . nrow - number of rows 2358 . irow - the row local indices 2359 . ncol - number of columns 2360 . icol - the column local indices 2361 . y - a logically two-dimensional array of values 2362 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2363 2364 Level: intermediate 2365 2366 Notes: 2367 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2368 2369 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2370 options cannot be mixed without intervening calls to the assembly 2371 routines. 2372 2373 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2374 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2375 2376 Developer Note: 2377 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2378 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2379 2380 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2381 `MatGetValuesLocal()` 2382 @*/ 2383 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2384 { 2385 PetscFunctionBeginHot; 2386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2387 PetscValidType(mat, 1); 2388 MatCheckPreallocated(mat, 1); 2389 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2390 PetscAssertPointer(irow, 3); 2391 PetscAssertPointer(icol, 5); 2392 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2393 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2394 if (PetscDefined(USE_DEBUG)) { 2395 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2396 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2397 } 2398 2399 if (mat->assembled) { 2400 mat->was_assembled = PETSC_TRUE; 2401 mat->assembled = PETSC_FALSE; 2402 } 2403 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2404 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2405 else { 2406 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2407 const PetscInt *irowm, *icolm; 2408 2409 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2410 bufr = buf; 2411 bufc = buf + nrow; 2412 irowm = bufr; 2413 icolm = bufc; 2414 } else { 2415 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2416 irowm = bufr; 2417 icolm = bufc; 2418 } 2419 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2420 else irowm = irow; 2421 if (mat->cmap->mapping) { 2422 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2423 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2424 } else icolm = irowm; 2425 } else icolm = icol; 2426 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2427 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2428 } 2429 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2430 PetscFunctionReturn(PETSC_SUCCESS); 2431 } 2432 2433 /*@C 2434 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2435 using a local ordering of the nodes a block at a time. 2436 2437 Not Collective 2438 2439 Input Parameters: 2440 + mat - the matrix 2441 . nrow - number of rows 2442 . irow - the row local indices 2443 . ncol - number of columns 2444 . icol - the column local indices 2445 . y - a logically two-dimensional array of values 2446 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2447 2448 Level: intermediate 2449 2450 Notes: 2451 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2452 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2453 2454 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2455 options cannot be mixed without intervening calls to the assembly 2456 routines. 2457 2458 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2459 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2460 2461 Developer Note: 2462 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2463 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2464 2465 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2466 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2467 @*/ 2468 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2469 { 2470 PetscFunctionBeginHot; 2471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2472 PetscValidType(mat, 1); 2473 MatCheckPreallocated(mat, 1); 2474 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2475 PetscAssertPointer(irow, 3); 2476 PetscAssertPointer(icol, 5); 2477 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2478 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2479 if (PetscDefined(USE_DEBUG)) { 2480 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2481 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); 2482 } 2483 2484 if (mat->assembled) { 2485 mat->was_assembled = PETSC_TRUE; 2486 mat->assembled = PETSC_FALSE; 2487 } 2488 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2489 PetscInt irbs, rbs; 2490 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2491 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2492 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2493 } 2494 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2495 PetscInt icbs, cbs; 2496 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2497 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2498 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2499 } 2500 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2501 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2502 else { 2503 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2504 const PetscInt *irowm, *icolm; 2505 2506 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2507 bufr = buf; 2508 bufc = buf + nrow; 2509 irowm = bufr; 2510 icolm = bufc; 2511 } else { 2512 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2513 irowm = bufr; 2514 icolm = bufc; 2515 } 2516 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2517 else irowm = irow; 2518 if (mat->cmap->mapping) { 2519 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2520 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2521 } else icolm = irowm; 2522 } else icolm = icol; 2523 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2524 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2525 } 2526 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2527 PetscFunctionReturn(PETSC_SUCCESS); 2528 } 2529 2530 /*@ 2531 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2532 2533 Collective 2534 2535 Input Parameters: 2536 + mat - the matrix 2537 - x - the vector to be multiplied 2538 2539 Output Parameter: 2540 . y - the result 2541 2542 Level: developer 2543 2544 Note: 2545 The vectors `x` and `y` cannot be the same. I.e., one cannot 2546 call `MatMultDiagonalBlock`(A,y,y). 2547 2548 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2549 @*/ 2550 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2551 { 2552 PetscFunctionBegin; 2553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2554 PetscValidType(mat, 1); 2555 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2556 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2557 2558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2560 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2561 MatCheckPreallocated(mat, 1); 2562 2563 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2564 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2565 PetscFunctionReturn(PETSC_SUCCESS); 2566 } 2567 2568 /*@ 2569 MatMult - Computes the matrix-vector product, $y = Ax$. 2570 2571 Neighbor-wise Collective 2572 2573 Input Parameters: 2574 + mat - the matrix 2575 - x - the vector to be multiplied 2576 2577 Output Parameter: 2578 . y - the result 2579 2580 Level: beginner 2581 2582 Note: 2583 The vectors `x` and `y` cannot be the same. I.e., one cannot 2584 call `MatMult`(A,y,y). 2585 2586 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2587 @*/ 2588 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2589 { 2590 PetscFunctionBegin; 2591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2592 PetscValidType(mat, 1); 2593 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2594 VecCheckAssembled(x); 2595 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2596 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2597 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2598 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2599 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); 2600 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); 2601 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); 2602 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); 2603 PetscCall(VecSetErrorIfLocked(y, 3)); 2604 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2605 MatCheckPreallocated(mat, 1); 2606 2607 PetscCall(VecLockReadPush(x)); 2608 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2609 PetscUseTypeMethod(mat, mult, x, y); 2610 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2611 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2612 PetscCall(VecLockReadPop(x)); 2613 PetscFunctionReturn(PETSC_SUCCESS); 2614 } 2615 2616 /*@ 2617 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2618 2619 Neighbor-wise Collective 2620 2621 Input Parameters: 2622 + mat - the matrix 2623 - x - the vector to be multiplied 2624 2625 Output Parameter: 2626 . y - the result 2627 2628 Level: beginner 2629 2630 Notes: 2631 The vectors `x` and `y` cannot be the same. I.e., one cannot 2632 call `MatMultTranspose`(A,y,y). 2633 2634 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2635 use `MatMultHermitianTranspose()` 2636 2637 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2638 @*/ 2639 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2640 { 2641 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2642 2643 PetscFunctionBegin; 2644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2645 PetscValidType(mat, 1); 2646 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2647 VecCheckAssembled(x); 2648 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2649 2650 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2651 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2652 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2653 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); 2654 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); 2655 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); 2656 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); 2657 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2658 MatCheckPreallocated(mat, 1); 2659 2660 if (!mat->ops->multtranspose) { 2661 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2662 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); 2663 } else op = mat->ops->multtranspose; 2664 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2665 PetscCall(VecLockReadPush(x)); 2666 PetscCall((*op)(mat, x, y)); 2667 PetscCall(VecLockReadPop(x)); 2668 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2669 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2670 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2671 PetscFunctionReturn(PETSC_SUCCESS); 2672 } 2673 2674 /*@ 2675 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2676 2677 Neighbor-wise Collective 2678 2679 Input Parameters: 2680 + mat - the matrix 2681 - x - the vector to be multiplied 2682 2683 Output Parameter: 2684 . y - the result 2685 2686 Level: beginner 2687 2688 Notes: 2689 The vectors `x` and `y` cannot be the same. I.e., one cannot 2690 call `MatMultHermitianTranspose`(A,y,y). 2691 2692 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2693 2694 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2695 2696 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2697 @*/ 2698 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2699 { 2700 PetscFunctionBegin; 2701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2702 PetscValidType(mat, 1); 2703 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2704 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2705 2706 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2707 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2708 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2709 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); 2710 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); 2711 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); 2712 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); 2713 MatCheckPreallocated(mat, 1); 2714 2715 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2716 #if defined(PETSC_USE_COMPLEX) 2717 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2718 PetscCall(VecLockReadPush(x)); 2719 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2720 else PetscUseTypeMethod(mat, mult, x, y); 2721 PetscCall(VecLockReadPop(x)); 2722 } else { 2723 Vec w; 2724 PetscCall(VecDuplicate(x, &w)); 2725 PetscCall(VecCopy(x, w)); 2726 PetscCall(VecConjugate(w)); 2727 PetscCall(MatMultTranspose(mat, w, y)); 2728 PetscCall(VecDestroy(&w)); 2729 PetscCall(VecConjugate(y)); 2730 } 2731 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2732 #else 2733 PetscCall(MatMultTranspose(mat, x, y)); 2734 #endif 2735 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2736 PetscFunctionReturn(PETSC_SUCCESS); 2737 } 2738 2739 /*@ 2740 MatMultAdd - Computes $v3 = v2 + A * v1$. 2741 2742 Neighbor-wise Collective 2743 2744 Input Parameters: 2745 + mat - the matrix 2746 . v1 - the vector to be multiplied by `mat` 2747 - v2 - the vector to be added to the result 2748 2749 Output Parameter: 2750 . v3 - the result 2751 2752 Level: beginner 2753 2754 Note: 2755 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2756 call `MatMultAdd`(A,v1,v2,v1). 2757 2758 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2759 @*/ 2760 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2761 { 2762 PetscFunctionBegin; 2763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2764 PetscValidType(mat, 1); 2765 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2766 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2767 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2768 2769 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2770 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2771 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); 2772 /* 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); 2773 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); */ 2774 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); 2775 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); 2776 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2777 MatCheckPreallocated(mat, 1); 2778 2779 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2780 PetscCall(VecLockReadPush(v1)); 2781 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2782 PetscCall(VecLockReadPop(v1)); 2783 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2784 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2785 PetscFunctionReturn(PETSC_SUCCESS); 2786 } 2787 2788 /*@ 2789 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2790 2791 Neighbor-wise Collective 2792 2793 Input Parameters: 2794 + mat - the matrix 2795 . v1 - the vector to be multiplied by the transpose of the matrix 2796 - v2 - the vector to be added to the result 2797 2798 Output Parameter: 2799 . v3 - the result 2800 2801 Level: beginner 2802 2803 Note: 2804 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2805 call `MatMultTransposeAdd`(A,v1,v2,v1). 2806 2807 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2808 @*/ 2809 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2810 { 2811 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2812 2813 PetscFunctionBegin; 2814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2815 PetscValidType(mat, 1); 2816 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2817 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2818 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2819 2820 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2821 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2822 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); 2823 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); 2824 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); 2825 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2826 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2827 MatCheckPreallocated(mat, 1); 2828 2829 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2830 PetscCall(VecLockReadPush(v1)); 2831 PetscCall((*op)(mat, v1, v2, v3)); 2832 PetscCall(VecLockReadPop(v1)); 2833 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2834 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2835 PetscFunctionReturn(PETSC_SUCCESS); 2836 } 2837 2838 /*@ 2839 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2840 2841 Neighbor-wise Collective 2842 2843 Input Parameters: 2844 + mat - the matrix 2845 . v1 - the vector to be multiplied by the Hermitian transpose 2846 - v2 - the vector to be added to the result 2847 2848 Output Parameter: 2849 . v3 - the result 2850 2851 Level: beginner 2852 2853 Note: 2854 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2855 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2856 2857 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2858 @*/ 2859 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2860 { 2861 PetscFunctionBegin; 2862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2863 PetscValidType(mat, 1); 2864 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2865 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2866 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2867 2868 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2869 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2870 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2871 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); 2872 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); 2873 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); 2874 MatCheckPreallocated(mat, 1); 2875 2876 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2877 PetscCall(VecLockReadPush(v1)); 2878 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2879 else { 2880 Vec w, z; 2881 PetscCall(VecDuplicate(v1, &w)); 2882 PetscCall(VecCopy(v1, w)); 2883 PetscCall(VecConjugate(w)); 2884 PetscCall(VecDuplicate(v3, &z)); 2885 PetscCall(MatMultTranspose(mat, w, z)); 2886 PetscCall(VecDestroy(&w)); 2887 PetscCall(VecConjugate(z)); 2888 if (v2 != v3) { 2889 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2890 } else { 2891 PetscCall(VecAXPY(v3, 1.0, z)); 2892 } 2893 PetscCall(VecDestroy(&z)); 2894 } 2895 PetscCall(VecLockReadPop(v1)); 2896 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2897 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2898 PetscFunctionReturn(PETSC_SUCCESS); 2899 } 2900 2901 /*@C 2902 MatGetFactorType - gets the type of factorization a matrix is 2903 2904 Not Collective 2905 2906 Input Parameter: 2907 . mat - the matrix 2908 2909 Output Parameter: 2910 . 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` 2911 2912 Level: intermediate 2913 2914 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2915 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2916 @*/ 2917 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2918 { 2919 PetscFunctionBegin; 2920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2921 PetscValidType(mat, 1); 2922 PetscAssertPointer(t, 2); 2923 *t = mat->factortype; 2924 PetscFunctionReturn(PETSC_SUCCESS); 2925 } 2926 2927 /*@C 2928 MatSetFactorType - sets the type of factorization a matrix is 2929 2930 Logically Collective 2931 2932 Input Parameters: 2933 + mat - the matrix 2934 - 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` 2935 2936 Level: intermediate 2937 2938 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2939 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2940 @*/ 2941 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2942 { 2943 PetscFunctionBegin; 2944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2945 PetscValidType(mat, 1); 2946 mat->factortype = t; 2947 PetscFunctionReturn(PETSC_SUCCESS); 2948 } 2949 2950 /*@C 2951 MatGetInfo - Returns information about matrix storage (number of 2952 nonzeros, memory, etc.). 2953 2954 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2955 2956 Input Parameters: 2957 + mat - the matrix 2958 - 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) 2959 2960 Output Parameter: 2961 . info - matrix information context 2962 2963 Options Database Key: 2964 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2965 2966 Notes: 2967 The `MatInfo` context contains a variety of matrix data, including 2968 number of nonzeros allocated and used, number of mallocs during 2969 matrix assembly, etc. Additional information for factored matrices 2970 is provided (such as the fill ratio, number of mallocs during 2971 factorization, etc.). 2972 2973 Example: 2974 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2975 data within the MatInfo context. For example, 2976 .vb 2977 MatInfo info; 2978 Mat A; 2979 double mal, nz_a, nz_u; 2980 2981 MatGetInfo(A, MAT_LOCAL, &info); 2982 mal = info.mallocs; 2983 nz_a = info.nz_allocated; 2984 .ve 2985 2986 Fortran users should declare info as a double precision 2987 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2988 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2989 a complete list of parameter names. 2990 .vb 2991 double precision info(MAT_INFO_SIZE) 2992 double precision mal, nz_a 2993 Mat A 2994 integer ierr 2995 2996 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2997 mal = info(MAT_INFO_MALLOCS) 2998 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2999 .ve 3000 3001 Level: intermediate 3002 3003 Developer Note: 3004 The Fortran interface is not autogenerated as the 3005 interface definition cannot be generated correctly [due to `MatInfo` argument] 3006 3007 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3008 @*/ 3009 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3010 { 3011 PetscFunctionBegin; 3012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3013 PetscValidType(mat, 1); 3014 PetscAssertPointer(info, 3); 3015 MatCheckPreallocated(mat, 1); 3016 PetscUseTypeMethod(mat, getinfo, flag, info); 3017 PetscFunctionReturn(PETSC_SUCCESS); 3018 } 3019 3020 /* 3021 This is used by external packages where it is not easy to get the info from the actual 3022 matrix factorization. 3023 */ 3024 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3025 { 3026 PetscFunctionBegin; 3027 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3028 PetscFunctionReturn(PETSC_SUCCESS); 3029 } 3030 3031 /*@C 3032 MatLUFactor - Performs in-place LU factorization of matrix. 3033 3034 Collective 3035 3036 Input Parameters: 3037 + mat - the matrix 3038 . row - row permutation 3039 . col - column permutation 3040 - info - options for factorization, includes 3041 .vb 3042 fill - expected fill as ratio of original fill. 3043 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3044 Run with the option -info to determine an optimal value to use 3045 .ve 3046 3047 Level: developer 3048 3049 Notes: 3050 Most users should employ the `KSP` interface for linear solvers 3051 instead of working directly with matrix algebra routines such as this. 3052 See, e.g., `KSPCreate()`. 3053 3054 This changes the state of the matrix to a factored matrix; it cannot be used 3055 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3056 3057 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3058 when not using `KSP`. 3059 3060 Developer Note: 3061 The Fortran interface is not autogenerated as the 3062 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3063 3064 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3065 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3066 @*/ 3067 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3068 { 3069 MatFactorInfo tinfo; 3070 3071 PetscFunctionBegin; 3072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3073 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3074 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3075 if (info) PetscAssertPointer(info, 4); 3076 PetscValidType(mat, 1); 3077 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3078 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3079 MatCheckPreallocated(mat, 1); 3080 if (!info) { 3081 PetscCall(MatFactorInfoInitialize(&tinfo)); 3082 info = &tinfo; 3083 } 3084 3085 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3086 PetscUseTypeMethod(mat, lufactor, row, col, info); 3087 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3088 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3089 PetscFunctionReturn(PETSC_SUCCESS); 3090 } 3091 3092 /*@C 3093 MatILUFactor - Performs in-place ILU factorization of matrix. 3094 3095 Collective 3096 3097 Input Parameters: 3098 + mat - the matrix 3099 . row - row permutation 3100 . col - column permutation 3101 - info - structure containing 3102 .vb 3103 levels - number of levels of fill. 3104 expected fill - as ratio of original fill. 3105 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3106 missing diagonal entries) 3107 .ve 3108 3109 Level: developer 3110 3111 Notes: 3112 Most users should employ the `KSP` interface for linear solvers 3113 instead of working directly with matrix algebra routines such as this. 3114 See, e.g., `KSPCreate()`. 3115 3116 Probably really in-place only when level of fill is zero, otherwise allocates 3117 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3118 when not using `KSP`. 3119 3120 Developer Note: 3121 The Fortran interface is not autogenerated as the 3122 interface definition cannot be generated correctly [due to MatFactorInfo] 3123 3124 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3125 @*/ 3126 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3127 { 3128 PetscFunctionBegin; 3129 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3130 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3131 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3132 PetscAssertPointer(info, 4); 3133 PetscValidType(mat, 1); 3134 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3135 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3136 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3137 MatCheckPreallocated(mat, 1); 3138 3139 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3140 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3141 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3142 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3143 PetscFunctionReturn(PETSC_SUCCESS); 3144 } 3145 3146 /*@C 3147 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3148 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3149 3150 Collective 3151 3152 Input Parameters: 3153 + fact - the factor matrix obtained with `MatGetFactor()` 3154 . mat - the matrix 3155 . row - the row permutation 3156 . col - the column permutation 3157 - info - options for factorization, includes 3158 .vb 3159 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3160 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3161 .ve 3162 3163 Level: developer 3164 3165 Notes: 3166 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3167 3168 Most users should employ the simplified `KSP` interface for linear solvers 3169 instead of working directly with matrix algebra routines such as this. 3170 See, e.g., `KSPCreate()`. 3171 3172 Developer Note: 3173 The Fortran interface is not autogenerated as the 3174 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3175 3176 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3177 @*/ 3178 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3179 { 3180 MatFactorInfo tinfo; 3181 3182 PetscFunctionBegin; 3183 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3185 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3186 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3187 if (info) PetscAssertPointer(info, 5); 3188 PetscValidType(fact, 1); 3189 PetscValidType(mat, 2); 3190 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3191 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3192 MatCheckPreallocated(mat, 2); 3193 if (!info) { 3194 PetscCall(MatFactorInfoInitialize(&tinfo)); 3195 info = &tinfo; 3196 } 3197 3198 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3199 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3200 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3201 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3202 PetscFunctionReturn(PETSC_SUCCESS); 3203 } 3204 3205 /*@C 3206 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3207 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3208 3209 Collective 3210 3211 Input Parameters: 3212 + fact - the factor matrix obtained with `MatGetFactor()` 3213 . mat - the matrix 3214 - info - options for factorization 3215 3216 Level: developer 3217 3218 Notes: 3219 See `MatLUFactor()` for in-place factorization. See 3220 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3221 3222 Most users should employ the `KSP` interface for linear solvers 3223 instead of working directly with matrix algebra routines such as this. 3224 See, e.g., `KSPCreate()`. 3225 3226 Developer Note: 3227 The Fortran interface is not autogenerated as the 3228 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3229 3230 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3231 @*/ 3232 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3233 { 3234 MatFactorInfo tinfo; 3235 3236 PetscFunctionBegin; 3237 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3239 PetscValidType(fact, 1); 3240 PetscValidType(mat, 2); 3241 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3242 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, 3243 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3244 3245 MatCheckPreallocated(mat, 2); 3246 if (!info) { 3247 PetscCall(MatFactorInfoInitialize(&tinfo)); 3248 info = &tinfo; 3249 } 3250 3251 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3252 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3253 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3254 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3255 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3256 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3257 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3258 PetscFunctionReturn(PETSC_SUCCESS); 3259 } 3260 3261 /*@C 3262 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3263 symmetric matrix. 3264 3265 Collective 3266 3267 Input Parameters: 3268 + mat - the matrix 3269 . perm - row and column permutations 3270 - info - expected fill as ratio of original fill 3271 3272 Level: developer 3273 3274 Notes: 3275 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3276 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3277 3278 Most users should employ the `KSP` interface for linear solvers 3279 instead of working directly with matrix algebra routines such as this. 3280 See, e.g., `KSPCreate()`. 3281 3282 Developer Note: 3283 The Fortran interface is not autogenerated as the 3284 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3285 3286 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3287 `MatGetOrdering()` 3288 @*/ 3289 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3290 { 3291 MatFactorInfo tinfo; 3292 3293 PetscFunctionBegin; 3294 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3295 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3296 if (info) PetscAssertPointer(info, 3); 3297 PetscValidType(mat, 1); 3298 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3299 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3300 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3301 MatCheckPreallocated(mat, 1); 3302 if (!info) { 3303 PetscCall(MatFactorInfoInitialize(&tinfo)); 3304 info = &tinfo; 3305 } 3306 3307 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3308 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3309 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3310 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3311 PetscFunctionReturn(PETSC_SUCCESS); 3312 } 3313 3314 /*@C 3315 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3316 of a symmetric matrix. 3317 3318 Collective 3319 3320 Input Parameters: 3321 + fact - the factor matrix obtained with `MatGetFactor()` 3322 . mat - the matrix 3323 . perm - row and column permutations 3324 - info - options for factorization, includes 3325 .vb 3326 fill - expected fill as ratio of original fill. 3327 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3328 Run with the option -info to determine an optimal value to use 3329 .ve 3330 3331 Level: developer 3332 3333 Notes: 3334 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3335 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3336 3337 Most users should employ the `KSP` interface for linear solvers 3338 instead of working directly with matrix algebra routines such as this. 3339 See, e.g., `KSPCreate()`. 3340 3341 Developer Note: 3342 The Fortran interface is not autogenerated as the 3343 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3344 3345 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3346 `MatGetOrdering()` 3347 @*/ 3348 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3349 { 3350 MatFactorInfo tinfo; 3351 3352 PetscFunctionBegin; 3353 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3354 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3355 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3356 if (info) PetscAssertPointer(info, 4); 3357 PetscValidType(fact, 1); 3358 PetscValidType(mat, 2); 3359 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3360 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3361 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3362 MatCheckPreallocated(mat, 2); 3363 if (!info) { 3364 PetscCall(MatFactorInfoInitialize(&tinfo)); 3365 info = &tinfo; 3366 } 3367 3368 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3369 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3370 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3371 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3372 PetscFunctionReturn(PETSC_SUCCESS); 3373 } 3374 3375 /*@C 3376 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3377 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3378 `MatCholeskyFactorSymbolic()`. 3379 3380 Collective 3381 3382 Input Parameters: 3383 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3384 . mat - the initial matrix that is to be factored 3385 - info - options for factorization 3386 3387 Level: developer 3388 3389 Note: 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()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3399 @*/ 3400 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3401 { 3402 MatFactorInfo tinfo; 3403 3404 PetscFunctionBegin; 3405 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3407 PetscValidType(fact, 1); 3408 PetscValidType(mat, 2); 3409 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3410 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, 3411 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3412 MatCheckPreallocated(mat, 2); 3413 if (!info) { 3414 PetscCall(MatFactorInfoInitialize(&tinfo)); 3415 info = &tinfo; 3416 } 3417 3418 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3419 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3420 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3421 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3422 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3423 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3424 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3425 PetscFunctionReturn(PETSC_SUCCESS); 3426 } 3427 3428 /*@ 3429 MatQRFactor - Performs in-place QR factorization of matrix. 3430 3431 Collective 3432 3433 Input Parameters: 3434 + mat - the matrix 3435 . col - column permutation 3436 - info - options for factorization, includes 3437 .vb 3438 fill - expected fill as ratio of original fill. 3439 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3440 Run with the option -info to determine an optimal value to use 3441 .ve 3442 3443 Level: developer 3444 3445 Notes: 3446 Most users should employ the `KSP` interface for linear solvers 3447 instead of working directly with matrix algebra routines such as this. 3448 See, e.g., `KSPCreate()`. 3449 3450 This changes the state of the matrix to a factored matrix; it cannot be used 3451 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3452 3453 Developer Note: 3454 The Fortran interface is not autogenerated as the 3455 interface definition cannot be generated correctly [due to MatFactorInfo] 3456 3457 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3458 `MatSetUnfactored()` 3459 @*/ 3460 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3461 { 3462 PetscFunctionBegin; 3463 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3464 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3465 if (info) PetscAssertPointer(info, 3); 3466 PetscValidType(mat, 1); 3467 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3468 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3469 MatCheckPreallocated(mat, 1); 3470 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3471 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3472 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3473 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3474 PetscFunctionReturn(PETSC_SUCCESS); 3475 } 3476 3477 /*@ 3478 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3479 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3480 3481 Collective 3482 3483 Input Parameters: 3484 + fact - the factor matrix obtained with `MatGetFactor()` 3485 . mat - the matrix 3486 . col - column permutation 3487 - info - options for factorization, includes 3488 .vb 3489 fill - expected fill as ratio of original fill. 3490 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3491 Run with the option -info to determine an optimal value to use 3492 .ve 3493 3494 Level: developer 3495 3496 Note: 3497 Most users should employ the `KSP` interface for linear solvers 3498 instead of working directly with matrix algebra routines such as this. 3499 See, e.g., `KSPCreate()`. 3500 3501 Developer Note: 3502 The Fortran interface is not autogenerated as the 3503 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3504 3505 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3506 @*/ 3507 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3508 { 3509 MatFactorInfo tinfo; 3510 3511 PetscFunctionBegin; 3512 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3514 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3515 if (info) PetscAssertPointer(info, 4); 3516 PetscValidType(fact, 1); 3517 PetscValidType(mat, 2); 3518 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3519 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3520 MatCheckPreallocated(mat, 2); 3521 if (!info) { 3522 PetscCall(MatFactorInfoInitialize(&tinfo)); 3523 info = &tinfo; 3524 } 3525 3526 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3527 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3528 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3529 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3530 PetscFunctionReturn(PETSC_SUCCESS); 3531 } 3532 3533 /*@ 3534 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3535 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3536 3537 Collective 3538 3539 Input Parameters: 3540 + fact - the factor matrix obtained with `MatGetFactor()` 3541 . mat - the matrix 3542 - info - options for factorization 3543 3544 Level: developer 3545 3546 Notes: 3547 See `MatQRFactor()` for in-place factorization. 3548 3549 Most users should employ the `KSP` interface for linear solvers 3550 instead of working directly with matrix algebra routines such as this. 3551 See, e.g., `KSPCreate()`. 3552 3553 Developer Note: 3554 The Fortran interface is not autogenerated as the 3555 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3556 3557 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3558 @*/ 3559 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3560 { 3561 MatFactorInfo tinfo; 3562 3563 PetscFunctionBegin; 3564 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3566 PetscValidType(fact, 1); 3567 PetscValidType(mat, 2); 3568 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3569 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, 3570 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3571 3572 MatCheckPreallocated(mat, 2); 3573 if (!info) { 3574 PetscCall(MatFactorInfoInitialize(&tinfo)); 3575 info = &tinfo; 3576 } 3577 3578 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3579 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3580 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3581 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3582 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3583 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3584 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3585 PetscFunctionReturn(PETSC_SUCCESS); 3586 } 3587 3588 /*@ 3589 MatSolve - Solves $A x = b$, given a factored matrix. 3590 3591 Neighbor-wise Collective 3592 3593 Input Parameters: 3594 + mat - the factored matrix 3595 - b - the right-hand-side vector 3596 3597 Output Parameter: 3598 . x - the result vector 3599 3600 Level: developer 3601 3602 Notes: 3603 The vectors `b` and `x` cannot be the same. I.e., one cannot 3604 call `MatSolve`(A,x,x). 3605 3606 Most users should employ the `KSP` interface for linear solvers 3607 instead of working directly with matrix algebra routines such as this. 3608 See, e.g., `KSPCreate()`. 3609 3610 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3611 @*/ 3612 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3613 { 3614 PetscFunctionBegin; 3615 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3616 PetscValidType(mat, 1); 3617 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3618 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3619 PetscCheckSameComm(mat, 1, b, 2); 3620 PetscCheckSameComm(mat, 1, x, 3); 3621 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3622 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); 3623 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); 3624 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); 3625 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3626 MatCheckPreallocated(mat, 1); 3627 3628 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3629 if (mat->factorerrortype) { 3630 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3631 PetscCall(VecSetInf(x)); 3632 } else PetscUseTypeMethod(mat, solve, b, x); 3633 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3634 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3635 PetscFunctionReturn(PETSC_SUCCESS); 3636 } 3637 3638 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3639 { 3640 Vec b, x; 3641 PetscInt N, i; 3642 PetscErrorCode (*f)(Mat, Vec, Vec); 3643 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3644 3645 PetscFunctionBegin; 3646 if (A->factorerrortype) { 3647 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3648 PetscCall(MatSetInf(X)); 3649 PetscFunctionReturn(PETSC_SUCCESS); 3650 } 3651 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3652 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3653 PetscCall(MatBoundToCPU(A, &Abound)); 3654 if (!Abound) { 3655 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3656 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3657 } 3658 #if PetscDefined(HAVE_CUDA) 3659 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3660 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3661 #elif PetscDefined(HAVE_HIP) 3662 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3663 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3664 #endif 3665 PetscCall(MatGetSize(B, NULL, &N)); 3666 for (i = 0; i < N; i++) { 3667 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3668 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3669 PetscCall((*f)(A, b, x)); 3670 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3671 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3672 } 3673 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3674 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3675 PetscFunctionReturn(PETSC_SUCCESS); 3676 } 3677 3678 /*@ 3679 MatMatSolve - Solves $A X = B$, given a factored matrix. 3680 3681 Neighbor-wise Collective 3682 3683 Input Parameters: 3684 + A - the factored matrix 3685 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3686 3687 Output Parameter: 3688 . X - the result matrix (dense matrix) 3689 3690 Level: developer 3691 3692 Note: 3693 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3694 otherwise, `B` and `X` cannot be the same. 3695 3696 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3697 @*/ 3698 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3699 { 3700 PetscFunctionBegin; 3701 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3702 PetscValidType(A, 1); 3703 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3704 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3705 PetscCheckSameComm(A, 1, B, 2); 3706 PetscCheckSameComm(A, 1, X, 3); 3707 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); 3708 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); 3709 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"); 3710 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3711 MatCheckPreallocated(A, 1); 3712 3713 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3714 if (!A->ops->matsolve) { 3715 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3716 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3717 } else PetscUseTypeMethod(A, matsolve, B, X); 3718 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3719 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3720 PetscFunctionReturn(PETSC_SUCCESS); 3721 } 3722 3723 /*@ 3724 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3725 3726 Neighbor-wise Collective 3727 3728 Input Parameters: 3729 + A - the factored matrix 3730 - B - the right-hand-side matrix (`MATDENSE` matrix) 3731 3732 Output Parameter: 3733 . X - the result matrix (dense matrix) 3734 3735 Level: developer 3736 3737 Note: 3738 The matrices `B` and `X` cannot be the same. I.e., one cannot 3739 call `MatMatSolveTranspose`(A,X,X). 3740 3741 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3742 @*/ 3743 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3744 { 3745 PetscFunctionBegin; 3746 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3747 PetscValidType(A, 1); 3748 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3749 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3750 PetscCheckSameComm(A, 1, B, 2); 3751 PetscCheckSameComm(A, 1, X, 3); 3752 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3753 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); 3754 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); 3755 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); 3756 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"); 3757 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3758 MatCheckPreallocated(A, 1); 3759 3760 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3761 if (!A->ops->matsolvetranspose) { 3762 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3763 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3764 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3765 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3766 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3767 PetscFunctionReturn(PETSC_SUCCESS); 3768 } 3769 3770 /*@ 3771 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3772 3773 Neighbor-wise Collective 3774 3775 Input Parameters: 3776 + A - the factored matrix 3777 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3778 3779 Output Parameter: 3780 . X - the result matrix (dense matrix) 3781 3782 Level: developer 3783 3784 Note: 3785 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 3786 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3787 3788 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3789 @*/ 3790 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3791 { 3792 PetscFunctionBegin; 3793 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3794 PetscValidType(A, 1); 3795 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3796 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3797 PetscCheckSameComm(A, 1, Bt, 2); 3798 PetscCheckSameComm(A, 1, X, 3); 3799 3800 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3801 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); 3802 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); 3803 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"); 3804 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3805 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3806 MatCheckPreallocated(A, 1); 3807 3808 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3809 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3810 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3811 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3812 PetscFunctionReturn(PETSC_SUCCESS); 3813 } 3814 3815 /*@ 3816 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3817 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3818 3819 Neighbor-wise Collective 3820 3821 Input Parameters: 3822 + mat - the factored matrix 3823 - b - the right-hand-side vector 3824 3825 Output Parameter: 3826 . x - the result vector 3827 3828 Level: developer 3829 3830 Notes: 3831 `MatSolve()` should be used for most applications, as it performs 3832 a forward solve followed by a backward solve. 3833 3834 The vectors `b` and `x` cannot be the same, i.e., one cannot 3835 call `MatForwardSolve`(A,x,x). 3836 3837 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3838 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3839 `MatForwardSolve()` solves $U^T*D y = b$, and 3840 `MatBackwardSolve()` solves $U x = y$. 3841 Thus they do not provide a symmetric preconditioner. 3842 3843 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3844 @*/ 3845 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3846 { 3847 PetscFunctionBegin; 3848 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3849 PetscValidType(mat, 1); 3850 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3851 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3852 PetscCheckSameComm(mat, 1, b, 2); 3853 PetscCheckSameComm(mat, 1, x, 3); 3854 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3855 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); 3856 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); 3857 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); 3858 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3859 MatCheckPreallocated(mat, 1); 3860 3861 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3862 PetscUseTypeMethod(mat, forwardsolve, b, x); 3863 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3864 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3865 PetscFunctionReturn(PETSC_SUCCESS); 3866 } 3867 3868 /*@ 3869 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3870 $D^(1/2) U 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 `MatBackwardSolve`(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`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3897 @*/ 3898 PetscErrorCode MatBackwardSolve(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_BackwardSolve, mat, b, x, 0)); 3915 PetscUseTypeMethod(mat, backwardsolve, b, x); 3916 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3917 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3918 PetscFunctionReturn(PETSC_SUCCESS); 3919 } 3920 3921 /*@ 3922 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3923 3924 Neighbor-wise Collective 3925 3926 Input Parameters: 3927 + mat - the factored matrix 3928 . b - the right-hand-side vector 3929 - y - the vector to be added to 3930 3931 Output Parameter: 3932 . x - the result vector 3933 3934 Level: developer 3935 3936 Note: 3937 The vectors `b` and `x` cannot be the same. I.e., one cannot 3938 call `MatSolveAdd`(A,x,y,x). 3939 3940 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3941 @*/ 3942 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3943 { 3944 PetscScalar one = 1.0; 3945 Vec tmp; 3946 3947 PetscFunctionBegin; 3948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3949 PetscValidType(mat, 1); 3950 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3951 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3952 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3953 PetscCheckSameComm(mat, 1, b, 2); 3954 PetscCheckSameComm(mat, 1, y, 3); 3955 PetscCheckSameComm(mat, 1, x, 4); 3956 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3957 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); 3958 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); 3959 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); 3960 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); 3961 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); 3962 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3963 MatCheckPreallocated(mat, 1); 3964 3965 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3966 if (mat->factorerrortype) { 3967 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3968 PetscCall(VecSetInf(x)); 3969 } else if (mat->ops->solveadd) { 3970 PetscUseTypeMethod(mat, solveadd, b, y, x); 3971 } else { 3972 /* do the solve then the add manually */ 3973 if (x != y) { 3974 PetscCall(MatSolve(mat, b, x)); 3975 PetscCall(VecAXPY(x, one, y)); 3976 } else { 3977 PetscCall(VecDuplicate(x, &tmp)); 3978 PetscCall(VecCopy(x, tmp)); 3979 PetscCall(MatSolve(mat, b, x)); 3980 PetscCall(VecAXPY(x, one, tmp)); 3981 PetscCall(VecDestroy(&tmp)); 3982 } 3983 } 3984 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3985 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3986 PetscFunctionReturn(PETSC_SUCCESS); 3987 } 3988 3989 /*@ 3990 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 3991 3992 Neighbor-wise Collective 3993 3994 Input Parameters: 3995 + mat - the factored matrix 3996 - b - the right-hand-side vector 3997 3998 Output Parameter: 3999 . x - the result vector 4000 4001 Level: developer 4002 4003 Notes: 4004 The vectors `b` and `x` cannot be the same. I.e., one cannot 4005 call `MatSolveTranspose`(A,x,x). 4006 4007 Most users should employ the `KSP` interface for linear solvers 4008 instead of working directly with matrix algebra routines such as this. 4009 See, e.g., `KSPCreate()`. 4010 4011 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4012 @*/ 4013 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4014 { 4015 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4016 4017 PetscFunctionBegin; 4018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4019 PetscValidType(mat, 1); 4020 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4021 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4022 PetscCheckSameComm(mat, 1, b, 2); 4023 PetscCheckSameComm(mat, 1, x, 3); 4024 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4025 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); 4026 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); 4027 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4028 MatCheckPreallocated(mat, 1); 4029 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4030 if (mat->factorerrortype) { 4031 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4032 PetscCall(VecSetInf(x)); 4033 } else { 4034 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4035 PetscCall((*f)(mat, b, x)); 4036 } 4037 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4038 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4039 PetscFunctionReturn(PETSC_SUCCESS); 4040 } 4041 4042 /*@ 4043 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4044 factored matrix. 4045 4046 Neighbor-wise Collective 4047 4048 Input Parameters: 4049 + mat - the factored matrix 4050 . b - the right-hand-side vector 4051 - y - the vector to be added to 4052 4053 Output Parameter: 4054 . x - the result vector 4055 4056 Level: developer 4057 4058 Note: 4059 The vectors `b` and `x` cannot be the same. I.e., one cannot 4060 call `MatSolveTransposeAdd`(A,x,y,x). 4061 4062 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4063 @*/ 4064 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4065 { 4066 PetscScalar one = 1.0; 4067 Vec tmp; 4068 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4069 4070 PetscFunctionBegin; 4071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4072 PetscValidType(mat, 1); 4073 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4074 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4075 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4076 PetscCheckSameComm(mat, 1, b, 2); 4077 PetscCheckSameComm(mat, 1, y, 3); 4078 PetscCheckSameComm(mat, 1, x, 4); 4079 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4080 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); 4081 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); 4082 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); 4083 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); 4084 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4085 MatCheckPreallocated(mat, 1); 4086 4087 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4088 if (mat->factorerrortype) { 4089 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4090 PetscCall(VecSetInf(x)); 4091 } else if (f) { 4092 PetscCall((*f)(mat, b, y, x)); 4093 } else { 4094 /* do the solve then the add manually */ 4095 if (x != y) { 4096 PetscCall(MatSolveTranspose(mat, b, x)); 4097 PetscCall(VecAXPY(x, one, y)); 4098 } else { 4099 PetscCall(VecDuplicate(x, &tmp)); 4100 PetscCall(VecCopy(x, tmp)); 4101 PetscCall(MatSolveTranspose(mat, b, x)); 4102 PetscCall(VecAXPY(x, one, tmp)); 4103 PetscCall(VecDestroy(&tmp)); 4104 } 4105 } 4106 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4107 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4108 PetscFunctionReturn(PETSC_SUCCESS); 4109 } 4110 4111 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4112 /*@ 4113 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4114 4115 Neighbor-wise Collective 4116 4117 Input Parameters: 4118 + mat - the matrix 4119 . b - the right-hand side 4120 . omega - the relaxation factor 4121 . flag - flag indicating the type of SOR (see below) 4122 . shift - diagonal shift 4123 . its - the number of iterations 4124 - lits - the number of local iterations 4125 4126 Output Parameter: 4127 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4128 4129 SOR Flags: 4130 + `SOR_FORWARD_SWEEP` - forward SOR 4131 . `SOR_BACKWARD_SWEEP` - backward SOR 4132 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4133 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4134 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4135 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4136 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4137 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4138 upper/lower triangular part of matrix to 4139 vector (with omega) 4140 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4141 4142 Level: developer 4143 4144 Notes: 4145 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4146 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4147 on each processor. 4148 4149 Application programmers will not generally use `MatSOR()` directly, 4150 but instead will employ the `KSP`/`PC` interface. 4151 4152 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4153 4154 Most users should employ the `KSP` interface for linear solvers 4155 instead of working directly with matrix algebra routines such as this. 4156 See, e.g., `KSPCreate()`. 4157 4158 Vectors `x` and `b` CANNOT be the same 4159 4160 The flags are implemented as bitwise inclusive or operations. 4161 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4162 to specify a zero initial guess for SSOR. 4163 4164 Developer Note: 4165 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4166 4167 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4168 @*/ 4169 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4170 { 4171 PetscFunctionBegin; 4172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4173 PetscValidType(mat, 1); 4174 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4175 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4176 PetscCheckSameComm(mat, 1, b, 2); 4177 PetscCheckSameComm(mat, 1, x, 8); 4178 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4179 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4180 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); 4181 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); 4182 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); 4183 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4184 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4185 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4186 4187 MatCheckPreallocated(mat, 1); 4188 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4189 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4190 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4191 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4192 PetscFunctionReturn(PETSC_SUCCESS); 4193 } 4194 4195 /* 4196 Default matrix copy routine. 4197 */ 4198 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4199 { 4200 PetscInt i, rstart = 0, rend = 0, nz; 4201 const PetscInt *cwork; 4202 const PetscScalar *vwork; 4203 4204 PetscFunctionBegin; 4205 if (B->assembled) PetscCall(MatZeroEntries(B)); 4206 if (str == SAME_NONZERO_PATTERN) { 4207 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4208 for (i = rstart; i < rend; i++) { 4209 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4210 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4211 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4212 } 4213 } else { 4214 PetscCall(MatAYPX(B, 0.0, A, str)); 4215 } 4216 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4217 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4218 PetscFunctionReturn(PETSC_SUCCESS); 4219 } 4220 4221 /*@ 4222 MatCopy - Copies a matrix to another matrix. 4223 4224 Collective 4225 4226 Input Parameters: 4227 + A - the matrix 4228 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4229 4230 Output Parameter: 4231 . B - where the copy is put 4232 4233 Level: intermediate 4234 4235 Notes: 4236 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4237 4238 `MatCopy()` copies the matrix entries of a matrix to another existing 4239 matrix (after first zeroing the second matrix). A related routine is 4240 `MatConvert()`, which first creates a new matrix and then copies the data. 4241 4242 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4243 @*/ 4244 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4245 { 4246 PetscInt i; 4247 4248 PetscFunctionBegin; 4249 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4250 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4251 PetscValidType(A, 1); 4252 PetscValidType(B, 2); 4253 PetscCheckSameComm(A, 1, B, 2); 4254 MatCheckPreallocated(B, 2); 4255 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4256 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4257 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, 4258 A->cmap->N, B->cmap->N); 4259 MatCheckPreallocated(A, 1); 4260 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4261 4262 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4263 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4264 else PetscCall(MatCopy_Basic(A, B, str)); 4265 4266 B->stencil.dim = A->stencil.dim; 4267 B->stencil.noc = A->stencil.noc; 4268 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4269 B->stencil.dims[i] = A->stencil.dims[i]; 4270 B->stencil.starts[i] = A->stencil.starts[i]; 4271 } 4272 4273 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4274 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4275 PetscFunctionReturn(PETSC_SUCCESS); 4276 } 4277 4278 /*@C 4279 MatConvert - Converts a matrix to another matrix, either of the same 4280 or different type. 4281 4282 Collective 4283 4284 Input Parameters: 4285 + mat - the matrix 4286 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4287 same type as the original matrix. 4288 - reuse - denotes if the destination matrix is to be created or reused. 4289 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 4290 `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). 4291 4292 Output Parameter: 4293 . M - pointer to place new matrix 4294 4295 Level: intermediate 4296 4297 Notes: 4298 `MatConvert()` first creates a new matrix and then copies the data from 4299 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4300 entries of one matrix to another already existing matrix context. 4301 4302 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4303 the MPI communicator of the generated matrix is always the same as the communicator 4304 of the input matrix. 4305 4306 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4307 @*/ 4308 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4309 { 4310 PetscBool sametype, issame, flg; 4311 PetscBool3 issymmetric, ishermitian; 4312 char convname[256], mtype[256]; 4313 Mat B; 4314 4315 PetscFunctionBegin; 4316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4317 PetscValidType(mat, 1); 4318 PetscAssertPointer(M, 4); 4319 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4320 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4321 MatCheckPreallocated(mat, 1); 4322 4323 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4324 if (flg) newtype = mtype; 4325 4326 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4327 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4328 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4329 if (reuse == MAT_REUSE_MATRIX) { 4330 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4331 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4332 } 4333 4334 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4335 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4336 PetscFunctionReturn(PETSC_SUCCESS); 4337 } 4338 4339 /* Cache Mat options because some converters use MatHeaderReplace */ 4340 issymmetric = mat->symmetric; 4341 ishermitian = mat->hermitian; 4342 4343 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4344 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4345 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4346 } else { 4347 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4348 const char *prefix[3] = {"seq", "mpi", ""}; 4349 PetscInt i; 4350 /* 4351 Order of precedence: 4352 0) See if newtype is a superclass of the current matrix. 4353 1) See if a specialized converter is known to the current matrix. 4354 2) See if a specialized converter is known to the desired matrix class. 4355 3) See if a good general converter is registered for the desired class 4356 (as of 6/27/03 only MATMPIADJ falls into this category). 4357 4) See if a good general converter is known for the current matrix. 4358 5) Use a really basic converter. 4359 */ 4360 4361 /* 0) See if newtype is a superclass of the current matrix. 4362 i.e mat is mpiaij and newtype is aij */ 4363 for (i = 0; i < 2; i++) { 4364 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4366 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4367 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4368 if (flg) { 4369 if (reuse == MAT_INPLACE_MATRIX) { 4370 PetscCall(PetscInfo(mat, "Early return\n")); 4371 PetscFunctionReturn(PETSC_SUCCESS); 4372 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4373 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4374 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4375 PetscFunctionReturn(PETSC_SUCCESS); 4376 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4377 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4378 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4379 PetscFunctionReturn(PETSC_SUCCESS); 4380 } 4381 } 4382 } 4383 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4384 for (i = 0; i < 3; i++) { 4385 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4386 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4387 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4388 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4389 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4390 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4391 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4392 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4393 if (conv) goto foundconv; 4394 } 4395 4396 /* 2) See if a specialized converter is known to the desired matrix class. */ 4397 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4398 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4399 PetscCall(MatSetType(B, newtype)); 4400 for (i = 0; i < 3; i++) { 4401 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4402 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4403 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4404 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4405 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4406 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4407 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4408 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4409 if (conv) { 4410 PetscCall(MatDestroy(&B)); 4411 goto foundconv; 4412 } 4413 } 4414 4415 /* 3) See if a good general converter is registered for the desired class */ 4416 conv = B->ops->convertfrom; 4417 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4418 PetscCall(MatDestroy(&B)); 4419 if (conv) goto foundconv; 4420 4421 /* 4) See if a good general converter is known for the current matrix */ 4422 if (mat->ops->convert) conv = mat->ops->convert; 4423 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4424 if (conv) goto foundconv; 4425 4426 /* 5) Use a really basic converter. */ 4427 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4428 conv = MatConvert_Basic; 4429 4430 foundconv: 4431 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4432 PetscCall((*conv)(mat, newtype, reuse, M)); 4433 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4434 /* the block sizes must be same if the mappings are copied over */ 4435 (*M)->rmap->bs = mat->rmap->bs; 4436 (*M)->cmap->bs = mat->cmap->bs; 4437 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4438 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4439 (*M)->rmap->mapping = mat->rmap->mapping; 4440 (*M)->cmap->mapping = mat->cmap->mapping; 4441 } 4442 (*M)->stencil.dim = mat->stencil.dim; 4443 (*M)->stencil.noc = mat->stencil.noc; 4444 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4445 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4446 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4447 } 4448 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4449 } 4450 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4451 4452 /* Copy Mat options */ 4453 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4454 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4455 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4456 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4457 PetscFunctionReturn(PETSC_SUCCESS); 4458 } 4459 4460 /*@C 4461 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4462 4463 Not Collective 4464 4465 Input Parameter: 4466 . mat - the matrix, must be a factored matrix 4467 4468 Output Parameter: 4469 . type - the string name of the package (do not free this string) 4470 4471 Level: intermediate 4472 4473 Fortran Note: 4474 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4475 4476 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4477 @*/ 4478 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4479 { 4480 PetscErrorCode (*conv)(Mat, MatSolverType *); 4481 4482 PetscFunctionBegin; 4483 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4484 PetscValidType(mat, 1); 4485 PetscAssertPointer(type, 2); 4486 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4487 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4488 if (conv) PetscCall((*conv)(mat, type)); 4489 else *type = MATSOLVERPETSC; 4490 PetscFunctionReturn(PETSC_SUCCESS); 4491 } 4492 4493 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4494 struct _MatSolverTypeForSpecifcType { 4495 MatType mtype; 4496 /* no entry for MAT_FACTOR_NONE */ 4497 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4498 MatSolverTypeForSpecifcType next; 4499 }; 4500 4501 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4502 struct _MatSolverTypeHolder { 4503 char *name; 4504 MatSolverTypeForSpecifcType handlers; 4505 MatSolverTypeHolder next; 4506 }; 4507 4508 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4509 4510 /*@C 4511 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4512 4513 Input Parameters: 4514 + package - name of the package, for example petsc or superlu 4515 . mtype - the matrix type that works with this package 4516 . ftype - the type of factorization supported by the package 4517 - createfactor - routine that will create the factored matrix ready to be used 4518 4519 Level: developer 4520 4521 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4522 `MatGetFactor()` 4523 @*/ 4524 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4525 { 4526 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4527 PetscBool flg; 4528 MatSolverTypeForSpecifcType inext, iprev = NULL; 4529 4530 PetscFunctionBegin; 4531 PetscCall(MatInitializePackage()); 4532 if (!next) { 4533 PetscCall(PetscNew(&MatSolverTypeHolders)); 4534 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4535 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4536 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4537 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4538 PetscFunctionReturn(PETSC_SUCCESS); 4539 } 4540 while (next) { 4541 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4542 if (flg) { 4543 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4544 inext = next->handlers; 4545 while (inext) { 4546 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4547 if (flg) { 4548 inext->createfactor[(int)ftype - 1] = createfactor; 4549 PetscFunctionReturn(PETSC_SUCCESS); 4550 } 4551 iprev = inext; 4552 inext = inext->next; 4553 } 4554 PetscCall(PetscNew(&iprev->next)); 4555 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4556 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4557 PetscFunctionReturn(PETSC_SUCCESS); 4558 } 4559 prev = next; 4560 next = next->next; 4561 } 4562 PetscCall(PetscNew(&prev->next)); 4563 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4564 PetscCall(PetscNew(&prev->next->handlers)); 4565 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4566 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4567 PetscFunctionReturn(PETSC_SUCCESS); 4568 } 4569 4570 /*@C 4571 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4572 4573 Input Parameters: 4574 + 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 4575 . ftype - the type of factorization supported by the type 4576 - mtype - the matrix type that works with this type 4577 4578 Output Parameters: 4579 + foundtype - `PETSC_TRUE` if the type was registered 4580 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4581 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4582 4583 Calling sequence of `createfactor`: 4584 + A - the matrix providing the factor matrix 4585 . mtype - the `MatType` of the factor requested 4586 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4587 4588 Level: developer 4589 4590 Note: 4591 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4592 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4593 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4594 4595 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4596 `MatInitializePackage()` 4597 @*/ 4598 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4599 { 4600 MatSolverTypeHolder next = MatSolverTypeHolders; 4601 PetscBool flg; 4602 MatSolverTypeForSpecifcType inext; 4603 4604 PetscFunctionBegin; 4605 if (foundtype) *foundtype = PETSC_FALSE; 4606 if (foundmtype) *foundmtype = PETSC_FALSE; 4607 if (createfactor) *createfactor = NULL; 4608 4609 if (type) { 4610 while (next) { 4611 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4612 if (flg) { 4613 if (foundtype) *foundtype = PETSC_TRUE; 4614 inext = next->handlers; 4615 while (inext) { 4616 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4617 if (flg) { 4618 if (foundmtype) *foundmtype = PETSC_TRUE; 4619 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4620 PetscFunctionReturn(PETSC_SUCCESS); 4621 } 4622 inext = inext->next; 4623 } 4624 } 4625 next = next->next; 4626 } 4627 } else { 4628 while (next) { 4629 inext = next->handlers; 4630 while (inext) { 4631 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4632 if (flg && inext->createfactor[(int)ftype - 1]) { 4633 if (foundtype) *foundtype = PETSC_TRUE; 4634 if (foundmtype) *foundmtype = PETSC_TRUE; 4635 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4636 PetscFunctionReturn(PETSC_SUCCESS); 4637 } 4638 inext = inext->next; 4639 } 4640 next = next->next; 4641 } 4642 /* try with base classes inext->mtype */ 4643 next = MatSolverTypeHolders; 4644 while (next) { 4645 inext = next->handlers; 4646 while (inext) { 4647 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4648 if (flg && inext->createfactor[(int)ftype - 1]) { 4649 if (foundtype) *foundtype = PETSC_TRUE; 4650 if (foundmtype) *foundmtype = PETSC_TRUE; 4651 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4652 PetscFunctionReturn(PETSC_SUCCESS); 4653 } 4654 inext = inext->next; 4655 } 4656 next = next->next; 4657 } 4658 } 4659 PetscFunctionReturn(PETSC_SUCCESS); 4660 } 4661 4662 PetscErrorCode MatSolverTypeDestroy(void) 4663 { 4664 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4665 MatSolverTypeForSpecifcType inext, iprev; 4666 4667 PetscFunctionBegin; 4668 while (next) { 4669 PetscCall(PetscFree(next->name)); 4670 inext = next->handlers; 4671 while (inext) { 4672 PetscCall(PetscFree(inext->mtype)); 4673 iprev = inext; 4674 inext = inext->next; 4675 PetscCall(PetscFree(iprev)); 4676 } 4677 prev = next; 4678 next = next->next; 4679 PetscCall(PetscFree(prev)); 4680 } 4681 MatSolverTypeHolders = NULL; 4682 PetscFunctionReturn(PETSC_SUCCESS); 4683 } 4684 4685 /*@C 4686 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4687 4688 Logically Collective 4689 4690 Input Parameter: 4691 . mat - the matrix 4692 4693 Output Parameter: 4694 . flg - `PETSC_TRUE` if uses the ordering 4695 4696 Level: developer 4697 4698 Note: 4699 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4700 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4701 4702 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4703 @*/ 4704 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4705 { 4706 PetscFunctionBegin; 4707 *flg = mat->canuseordering; 4708 PetscFunctionReturn(PETSC_SUCCESS); 4709 } 4710 4711 /*@C 4712 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4713 4714 Logically Collective 4715 4716 Input Parameters: 4717 + mat - the matrix obtained with `MatGetFactor()` 4718 - ftype - the factorization type to be used 4719 4720 Output Parameter: 4721 . otype - the preferred ordering type 4722 4723 Level: developer 4724 4725 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4726 @*/ 4727 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4728 { 4729 PetscFunctionBegin; 4730 *otype = mat->preferredordering[ftype]; 4731 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4732 PetscFunctionReturn(PETSC_SUCCESS); 4733 } 4734 4735 /*@C 4736 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4737 4738 Collective 4739 4740 Input Parameters: 4741 + mat - the matrix 4742 . 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 4743 the other criteria is returned 4744 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4745 4746 Output Parameter: 4747 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4748 4749 Options Database Keys: 4750 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4751 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4752 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4753 4754 Level: intermediate 4755 4756 Notes: 4757 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4758 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4759 4760 Users usually access the factorization solvers via `KSP` 4761 4762 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4763 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 4764 4765 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4766 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4767 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4768 4769 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4770 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4771 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4772 4773 Developer Note: 4774 This should actually be called `MatCreateFactor()` since it creates a new factor object 4775 4776 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4777 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4778 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4779 @*/ 4780 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4781 { 4782 PetscBool foundtype, foundmtype; 4783 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4784 4785 PetscFunctionBegin; 4786 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4787 PetscValidType(mat, 1); 4788 4789 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4790 MatCheckPreallocated(mat, 1); 4791 4792 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4793 if (!foundtype) { 4794 if (type) { 4795 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], 4796 ((PetscObject)mat)->type_name, type); 4797 } else { 4798 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); 4799 } 4800 } 4801 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4802 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); 4803 4804 PetscCall((*conv)(mat, ftype, f)); 4805 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4806 PetscFunctionReturn(PETSC_SUCCESS); 4807 } 4808 4809 /*@C 4810 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4811 4812 Not Collective 4813 4814 Input Parameters: 4815 + mat - the matrix 4816 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4817 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4818 4819 Output Parameter: 4820 . flg - PETSC_TRUE if the factorization is available 4821 4822 Level: intermediate 4823 4824 Notes: 4825 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4826 such as pastix, superlu, mumps etc. 4827 4828 PETSc must have been ./configure to use the external solver, using the option --download-package 4829 4830 Developer Note: 4831 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4832 4833 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4834 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4835 @*/ 4836 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4837 { 4838 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4839 4840 PetscFunctionBegin; 4841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4842 PetscAssertPointer(flg, 4); 4843 4844 *flg = PETSC_FALSE; 4845 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4846 4847 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4848 MatCheckPreallocated(mat, 1); 4849 4850 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4851 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4852 PetscFunctionReturn(PETSC_SUCCESS); 4853 } 4854 4855 /*@ 4856 MatDuplicate - Duplicates a matrix including the non-zero structure. 4857 4858 Collective 4859 4860 Input Parameters: 4861 + mat - the matrix 4862 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4863 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4864 4865 Output Parameter: 4866 . M - pointer to place new matrix 4867 4868 Level: intermediate 4869 4870 Notes: 4871 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4872 4873 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4874 4875 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. 4876 4877 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4878 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4879 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4880 4881 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4882 @*/ 4883 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4884 { 4885 Mat B; 4886 VecType vtype; 4887 PetscInt i; 4888 PetscObject dm, container_h, container_d; 4889 void (*viewf)(void); 4890 4891 PetscFunctionBegin; 4892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4893 PetscValidType(mat, 1); 4894 PetscAssertPointer(M, 3); 4895 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4896 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4897 MatCheckPreallocated(mat, 1); 4898 4899 *M = NULL; 4900 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4901 PetscUseTypeMethod(mat, duplicate, op, M); 4902 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4903 B = *M; 4904 4905 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4906 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4907 PetscCall(MatGetVecType(mat, &vtype)); 4908 PetscCall(MatSetVecType(B, vtype)); 4909 4910 B->stencil.dim = mat->stencil.dim; 4911 B->stencil.noc = mat->stencil.noc; 4912 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4913 B->stencil.dims[i] = mat->stencil.dims[i]; 4914 B->stencil.starts[i] = mat->stencil.starts[i]; 4915 } 4916 4917 B->nooffproczerorows = mat->nooffproczerorows; 4918 B->nooffprocentries = mat->nooffprocentries; 4919 4920 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4921 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4922 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4923 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4924 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4925 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4926 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4927 PetscFunctionReturn(PETSC_SUCCESS); 4928 } 4929 4930 /*@ 4931 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4932 4933 Logically Collective 4934 4935 Input Parameter: 4936 . mat - the matrix 4937 4938 Output Parameter: 4939 . v - the diagonal of the matrix 4940 4941 Level: intermediate 4942 4943 Note: 4944 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4945 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4946 is larger than `ndiag`, the values of the remaining entries are unspecified. 4947 4948 Currently only correct in parallel for square matrices. 4949 4950 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4951 @*/ 4952 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4953 { 4954 PetscFunctionBegin; 4955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4956 PetscValidType(mat, 1); 4957 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4958 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4959 MatCheckPreallocated(mat, 1); 4960 if (PetscDefined(USE_DEBUG)) { 4961 PetscInt nv, row, col, ndiag; 4962 4963 PetscCall(VecGetLocalSize(v, &nv)); 4964 PetscCall(MatGetLocalSize(mat, &row, &col)); 4965 ndiag = PetscMin(row, col); 4966 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); 4967 } 4968 4969 PetscUseTypeMethod(mat, getdiagonal, v); 4970 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4971 PetscFunctionReturn(PETSC_SUCCESS); 4972 } 4973 4974 /*@C 4975 MatGetRowMin - Gets the minimum value (of the real part) of each 4976 row of the matrix 4977 4978 Logically Collective 4979 4980 Input Parameter: 4981 . mat - the matrix 4982 4983 Output Parameters: 4984 + v - the vector for storing the maximums 4985 - idx - the indices of the column found for each row (optional) 4986 4987 Level: intermediate 4988 4989 Note: 4990 The result of this call are the same as if one converted the matrix to dense format 4991 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4992 4993 This code is only implemented for a couple of matrix formats. 4994 4995 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4996 `MatGetRowMax()` 4997 @*/ 4998 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4999 { 5000 PetscFunctionBegin; 5001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5002 PetscValidType(mat, 1); 5003 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5004 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5005 5006 if (!mat->cmap->N) { 5007 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5008 if (idx) { 5009 PetscInt i, m = mat->rmap->n; 5010 for (i = 0; i < m; i++) idx[i] = -1; 5011 } 5012 } else { 5013 MatCheckPreallocated(mat, 1); 5014 } 5015 PetscUseTypeMethod(mat, getrowmin, v, idx); 5016 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5017 PetscFunctionReturn(PETSC_SUCCESS); 5018 } 5019 5020 /*@C 5021 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5022 row of the matrix 5023 5024 Logically Collective 5025 5026 Input Parameter: 5027 . mat - the matrix 5028 5029 Output Parameters: 5030 + v - the vector for storing the minimums 5031 - idx - the indices of the column found for each row (or `NULL` if not needed) 5032 5033 Level: intermediate 5034 5035 Notes: 5036 if a row is completely empty or has only 0.0 values then the `idx` value for that 5037 row is 0 (the first column). 5038 5039 This code is only implemented for a couple of matrix formats. 5040 5041 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5042 @*/ 5043 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5044 { 5045 PetscFunctionBegin; 5046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5047 PetscValidType(mat, 1); 5048 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5049 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5050 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5051 5052 if (!mat->cmap->N) { 5053 PetscCall(VecSet(v, 0.0)); 5054 if (idx) { 5055 PetscInt i, m = mat->rmap->n; 5056 for (i = 0; i < m; i++) idx[i] = -1; 5057 } 5058 } else { 5059 MatCheckPreallocated(mat, 1); 5060 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5061 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5062 } 5063 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5064 PetscFunctionReturn(PETSC_SUCCESS); 5065 } 5066 5067 /*@C 5068 MatGetRowMax - Gets the maximum value (of the real part) of each 5069 row of the matrix 5070 5071 Logically Collective 5072 5073 Input Parameter: 5074 . mat - the matrix 5075 5076 Output Parameters: 5077 + v - the vector for storing the maximums 5078 - idx - the indices of the column found for each row (optional) 5079 5080 Level: intermediate 5081 5082 Notes: 5083 The result of this call are the same as if one converted the matrix to dense format 5084 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5085 5086 This code is only implemented for a couple of matrix formats. 5087 5088 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5089 @*/ 5090 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5091 { 5092 PetscFunctionBegin; 5093 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5094 PetscValidType(mat, 1); 5095 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5097 5098 if (!mat->cmap->N) { 5099 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5100 if (idx) { 5101 PetscInt i, m = mat->rmap->n; 5102 for (i = 0; i < m; i++) idx[i] = -1; 5103 } 5104 } else { 5105 MatCheckPreallocated(mat, 1); 5106 PetscUseTypeMethod(mat, getrowmax, v, idx); 5107 } 5108 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5109 PetscFunctionReturn(PETSC_SUCCESS); 5110 } 5111 5112 /*@C 5113 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5114 row of the matrix 5115 5116 Logically Collective 5117 5118 Input Parameter: 5119 . mat - the matrix 5120 5121 Output Parameters: 5122 + v - the vector for storing the maximums 5123 - idx - the indices of the column found for each row (or `NULL` if not needed) 5124 5125 Level: intermediate 5126 5127 Notes: 5128 if a row is completely empty or has only 0.0 values then the `idx` value for that 5129 row is 0 (the first column). 5130 5131 This code is only implemented for a couple of matrix formats. 5132 5133 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5134 @*/ 5135 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5136 { 5137 PetscFunctionBegin; 5138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5139 PetscValidType(mat, 1); 5140 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5141 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5142 5143 if (!mat->cmap->N) { 5144 PetscCall(VecSet(v, 0.0)); 5145 if (idx) { 5146 PetscInt i, m = mat->rmap->n; 5147 for (i = 0; i < m; i++) idx[i] = -1; 5148 } 5149 } else { 5150 MatCheckPreallocated(mat, 1); 5151 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5152 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5153 } 5154 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5155 PetscFunctionReturn(PETSC_SUCCESS); 5156 } 5157 5158 /*@C 5159 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5160 5161 Logically Collective 5162 5163 Input Parameter: 5164 . mat - the matrix 5165 5166 Output Parameter: 5167 . v - the vector for storing the sum 5168 5169 Level: intermediate 5170 5171 This code is only implemented for a couple of matrix formats. 5172 5173 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5174 @*/ 5175 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5176 { 5177 PetscFunctionBegin; 5178 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5179 PetscValidType(mat, 1); 5180 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5181 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5182 5183 if (!mat->cmap->N) { 5184 PetscCall(VecSet(v, 0.0)); 5185 } else { 5186 MatCheckPreallocated(mat, 1); 5187 PetscUseTypeMethod(mat, getrowsumabs, v); 5188 } 5189 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5190 PetscFunctionReturn(PETSC_SUCCESS); 5191 } 5192 5193 /*@ 5194 MatGetRowSum - Gets the sum of each row of the matrix 5195 5196 Logically or Neighborhood Collective 5197 5198 Input Parameter: 5199 . mat - the matrix 5200 5201 Output Parameter: 5202 . v - the vector for storing the sum of rows 5203 5204 Level: intermediate 5205 5206 Note: 5207 This code is slow since it is not currently specialized for different formats 5208 5209 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5210 @*/ 5211 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5212 { 5213 Vec ones; 5214 5215 PetscFunctionBegin; 5216 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5217 PetscValidType(mat, 1); 5218 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5219 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5220 MatCheckPreallocated(mat, 1); 5221 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5222 PetscCall(VecSet(ones, 1.)); 5223 PetscCall(MatMult(mat, ones, v)); 5224 PetscCall(VecDestroy(&ones)); 5225 PetscFunctionReturn(PETSC_SUCCESS); 5226 } 5227 5228 /*@ 5229 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5230 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5231 5232 Collective 5233 5234 Input Parameter: 5235 . mat - the matrix to provide the transpose 5236 5237 Output Parameter: 5238 . 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 5239 5240 Level: advanced 5241 5242 Note: 5243 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 5244 routine allows bypassing that call. 5245 5246 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5247 @*/ 5248 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5249 { 5250 PetscContainer rB = NULL; 5251 MatParentState *rb = NULL; 5252 5253 PetscFunctionBegin; 5254 PetscCall(PetscNew(&rb)); 5255 rb->id = ((PetscObject)mat)->id; 5256 rb->state = 0; 5257 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5258 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5259 PetscCall(PetscContainerSetPointer(rB, rb)); 5260 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5261 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5262 PetscCall(PetscObjectDereference((PetscObject)rB)); 5263 PetscFunctionReturn(PETSC_SUCCESS); 5264 } 5265 5266 /*@ 5267 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5268 5269 Collective 5270 5271 Input Parameters: 5272 + mat - the matrix to transpose 5273 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5274 5275 Output Parameter: 5276 . B - the transpose 5277 5278 Level: intermediate 5279 5280 Notes: 5281 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5282 5283 `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 5284 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5285 5286 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. 5287 5288 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5289 5290 If mat is unchanged from the last call this function returns immediately without recomputing the result 5291 5292 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5293 5294 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5295 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5296 @*/ 5297 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5298 { 5299 PetscContainer rB = NULL; 5300 MatParentState *rb = NULL; 5301 5302 PetscFunctionBegin; 5303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5304 PetscValidType(mat, 1); 5305 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5306 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5307 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5308 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5309 MatCheckPreallocated(mat, 1); 5310 if (reuse == MAT_REUSE_MATRIX) { 5311 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5312 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5313 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5314 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5315 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5316 } 5317 5318 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5319 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5320 PetscUseTypeMethod(mat, transpose, reuse, B); 5321 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5322 } 5323 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5324 5325 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5326 if (reuse != MAT_INPLACE_MATRIX) { 5327 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5328 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5329 rb->state = ((PetscObject)mat)->state; 5330 rb->nonzerostate = mat->nonzerostate; 5331 } 5332 PetscFunctionReturn(PETSC_SUCCESS); 5333 } 5334 5335 /*@ 5336 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5337 5338 Collective 5339 5340 Input Parameter: 5341 . A - the matrix to transpose 5342 5343 Output Parameter: 5344 . 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 5345 numerical portion. 5346 5347 Level: intermediate 5348 5349 Note: 5350 This is not supported for many matrix types, use `MatTranspose()` in those cases 5351 5352 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5353 @*/ 5354 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5355 { 5356 PetscFunctionBegin; 5357 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5358 PetscValidType(A, 1); 5359 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5360 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5361 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5362 PetscUseTypeMethod(A, transposesymbolic, B); 5363 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5364 5365 PetscCall(MatTransposeSetPrecursor(A, *B)); 5366 PetscFunctionReturn(PETSC_SUCCESS); 5367 } 5368 5369 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5370 { 5371 PetscContainer rB; 5372 MatParentState *rb; 5373 5374 PetscFunctionBegin; 5375 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5376 PetscValidType(A, 1); 5377 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5378 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5379 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5380 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5381 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5382 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5383 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5384 PetscFunctionReturn(PETSC_SUCCESS); 5385 } 5386 5387 /*@ 5388 MatIsTranspose - Test whether a matrix is another one's transpose, 5389 or its own, in which case it tests symmetry. 5390 5391 Collective 5392 5393 Input Parameters: 5394 + A - the matrix to test 5395 . B - the matrix to test against, this can equal the first parameter 5396 - tol - tolerance, differences between entries smaller than this are counted as zero 5397 5398 Output Parameter: 5399 . flg - the result 5400 5401 Level: intermediate 5402 5403 Notes: 5404 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5405 test involves parallel copies of the block off-diagonal parts of the matrix. 5406 5407 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5408 @*/ 5409 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5410 { 5411 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5412 5413 PetscFunctionBegin; 5414 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5415 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5416 PetscAssertPointer(flg, 4); 5417 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5418 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5419 *flg = PETSC_FALSE; 5420 if (f && g) { 5421 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5422 PetscCall((*f)(A, B, tol, flg)); 5423 } else { 5424 MatType mattype; 5425 5426 PetscCall(MatGetType(f ? B : A, &mattype)); 5427 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5428 } 5429 PetscFunctionReturn(PETSC_SUCCESS); 5430 } 5431 5432 /*@ 5433 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5434 5435 Collective 5436 5437 Input Parameters: 5438 + mat - the matrix to transpose and complex conjugate 5439 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5440 5441 Output Parameter: 5442 . B - the Hermitian transpose 5443 5444 Level: intermediate 5445 5446 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5447 @*/ 5448 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5449 { 5450 PetscFunctionBegin; 5451 PetscCall(MatTranspose(mat, reuse, B)); 5452 #if defined(PETSC_USE_COMPLEX) 5453 PetscCall(MatConjugate(*B)); 5454 #endif 5455 PetscFunctionReturn(PETSC_SUCCESS); 5456 } 5457 5458 /*@ 5459 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5460 5461 Collective 5462 5463 Input Parameters: 5464 + A - the matrix to test 5465 . B - the matrix to test against, this can equal the first parameter 5466 - tol - tolerance, differences between entries smaller than this are counted as zero 5467 5468 Output Parameter: 5469 . flg - the result 5470 5471 Level: intermediate 5472 5473 Notes: 5474 Only available for `MATAIJ` matrices. 5475 5476 The sequential algorithm 5477 has a running time of the order of the number of nonzeros; the parallel 5478 test involves parallel copies of the block off-diagonal parts of the matrix. 5479 5480 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5481 @*/ 5482 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5483 { 5484 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5485 5486 PetscFunctionBegin; 5487 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5488 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5489 PetscAssertPointer(flg, 4); 5490 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5491 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5492 if (f && g) { 5493 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5494 PetscCall((*f)(A, B, tol, flg)); 5495 } 5496 PetscFunctionReturn(PETSC_SUCCESS); 5497 } 5498 5499 /*@ 5500 MatPermute - Creates a new matrix with rows and columns permuted from the 5501 original. 5502 5503 Collective 5504 5505 Input Parameters: 5506 + mat - the matrix to permute 5507 . row - row permutation, each processor supplies only the permutation for its rows 5508 - col - column permutation, each processor supplies only the permutation for its columns 5509 5510 Output Parameter: 5511 . B - the permuted matrix 5512 5513 Level: advanced 5514 5515 Note: 5516 The index sets map from row/col of permuted matrix to row/col of original matrix. 5517 The index sets should be on the same communicator as mat and have the same local sizes. 5518 5519 Developer Note: 5520 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5521 exploit the fact that row and col are permutations, consider implementing the 5522 more general `MatCreateSubMatrix()` instead. 5523 5524 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5525 @*/ 5526 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5527 { 5528 PetscFunctionBegin; 5529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5530 PetscValidType(mat, 1); 5531 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5532 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5533 PetscAssertPointer(B, 4); 5534 PetscCheckSameComm(mat, 1, row, 2); 5535 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5536 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5537 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5538 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5539 MatCheckPreallocated(mat, 1); 5540 5541 if (mat->ops->permute) { 5542 PetscUseTypeMethod(mat, permute, row, col, B); 5543 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5544 } else { 5545 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5546 } 5547 PetscFunctionReturn(PETSC_SUCCESS); 5548 } 5549 5550 /*@ 5551 MatEqual - Compares two matrices. 5552 5553 Collective 5554 5555 Input Parameters: 5556 + A - the first matrix 5557 - B - the second matrix 5558 5559 Output Parameter: 5560 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5561 5562 Level: intermediate 5563 5564 .seealso: [](ch_matrices), `Mat` 5565 @*/ 5566 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5567 { 5568 PetscFunctionBegin; 5569 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5570 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5571 PetscValidType(A, 1); 5572 PetscValidType(B, 2); 5573 PetscAssertPointer(flg, 3); 5574 PetscCheckSameComm(A, 1, B, 2); 5575 MatCheckPreallocated(A, 1); 5576 MatCheckPreallocated(B, 2); 5577 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5578 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5579 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, 5580 B->cmap->N); 5581 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5582 PetscUseTypeMethod(A, equal, B, flg); 5583 } else { 5584 PetscCall(MatMultEqual(A, B, 10, flg)); 5585 } 5586 PetscFunctionReturn(PETSC_SUCCESS); 5587 } 5588 5589 /*@ 5590 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5591 matrices that are stored as vectors. Either of the two scaling 5592 matrices can be `NULL`. 5593 5594 Collective 5595 5596 Input Parameters: 5597 + mat - the matrix to be scaled 5598 . l - the left scaling vector (or `NULL`) 5599 - r - the right scaling vector (or `NULL`) 5600 5601 Level: intermediate 5602 5603 Note: 5604 `MatDiagonalScale()` computes $A = LAR$, where 5605 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5606 The L scales the rows of the matrix, the R scales the columns of the matrix. 5607 5608 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5609 @*/ 5610 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5611 { 5612 PetscFunctionBegin; 5613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5614 PetscValidType(mat, 1); 5615 if (l) { 5616 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5617 PetscCheckSameComm(mat, 1, l, 2); 5618 } 5619 if (r) { 5620 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5621 PetscCheckSameComm(mat, 1, r, 3); 5622 } 5623 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5624 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5625 MatCheckPreallocated(mat, 1); 5626 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5627 5628 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5629 PetscUseTypeMethod(mat, diagonalscale, l, r); 5630 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5631 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5632 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5633 PetscFunctionReturn(PETSC_SUCCESS); 5634 } 5635 5636 /*@ 5637 MatScale - Scales all elements of a matrix by a given number. 5638 5639 Logically Collective 5640 5641 Input Parameters: 5642 + mat - the matrix to be scaled 5643 - a - the scaling value 5644 5645 Level: intermediate 5646 5647 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5648 @*/ 5649 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5650 { 5651 PetscFunctionBegin; 5652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5653 PetscValidType(mat, 1); 5654 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5655 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5656 PetscValidLogicalCollectiveScalar(mat, a, 2); 5657 MatCheckPreallocated(mat, 1); 5658 5659 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5660 if (a != (PetscScalar)1.0) { 5661 PetscUseTypeMethod(mat, scale, a); 5662 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5663 } 5664 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5665 PetscFunctionReturn(PETSC_SUCCESS); 5666 } 5667 5668 /*@ 5669 MatNorm - Calculates various norms of a matrix. 5670 5671 Collective 5672 5673 Input Parameters: 5674 + mat - the matrix 5675 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5676 5677 Output Parameter: 5678 . nrm - the resulting norm 5679 5680 Level: intermediate 5681 5682 .seealso: [](ch_matrices), `Mat` 5683 @*/ 5684 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5685 { 5686 PetscFunctionBegin; 5687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5688 PetscValidType(mat, 1); 5689 PetscAssertPointer(nrm, 3); 5690 5691 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5692 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5693 MatCheckPreallocated(mat, 1); 5694 5695 PetscUseTypeMethod(mat, norm, type, nrm); 5696 PetscFunctionReturn(PETSC_SUCCESS); 5697 } 5698 5699 /* 5700 This variable is used to prevent counting of MatAssemblyBegin() that 5701 are called from within a MatAssemblyEnd(). 5702 */ 5703 static PetscInt MatAssemblyEnd_InUse = 0; 5704 /*@ 5705 MatAssemblyBegin - Begins assembling the matrix. This routine should 5706 be called after completing all calls to `MatSetValues()`. 5707 5708 Collective 5709 5710 Input Parameters: 5711 + mat - the matrix 5712 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5713 5714 Level: beginner 5715 5716 Notes: 5717 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5718 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5719 5720 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5721 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5722 using the matrix. 5723 5724 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5725 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 5726 a global collective operation requiring all processes that share the matrix. 5727 5728 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5729 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5730 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5731 5732 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5733 @*/ 5734 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5735 { 5736 PetscFunctionBegin; 5737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5738 PetscValidType(mat, 1); 5739 MatCheckPreallocated(mat, 1); 5740 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5741 if (mat->assembled) { 5742 mat->was_assembled = PETSC_TRUE; 5743 mat->assembled = PETSC_FALSE; 5744 } 5745 5746 if (!MatAssemblyEnd_InUse) { 5747 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5748 PetscTryTypeMethod(mat, assemblybegin, type); 5749 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5750 } else PetscTryTypeMethod(mat, assemblybegin, type); 5751 PetscFunctionReturn(PETSC_SUCCESS); 5752 } 5753 5754 /*@ 5755 MatAssembled - Indicates if a matrix has been assembled and is ready for 5756 use; for example, in matrix-vector product. 5757 5758 Not Collective 5759 5760 Input Parameter: 5761 . mat - the matrix 5762 5763 Output Parameter: 5764 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5765 5766 Level: advanced 5767 5768 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5769 @*/ 5770 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5771 { 5772 PetscFunctionBegin; 5773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5774 PetscAssertPointer(assembled, 2); 5775 *assembled = mat->assembled; 5776 PetscFunctionReturn(PETSC_SUCCESS); 5777 } 5778 5779 /*@ 5780 MatAssemblyEnd - Completes assembling the matrix. This routine should 5781 be called after `MatAssemblyBegin()`. 5782 5783 Collective 5784 5785 Input Parameters: 5786 + mat - the matrix 5787 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5788 5789 Options Database Keys: 5790 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5791 . -mat_view ::ascii_info_detail - Prints more detailed info 5792 . -mat_view - Prints matrix in ASCII format 5793 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5794 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5795 . -display <name> - Sets display name (default is host) 5796 . -draw_pause <sec> - Sets number of seconds to pause after display 5797 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5798 . -viewer_socket_machine <machine> - Machine to use for socket 5799 . -viewer_socket_port <port> - Port number to use for socket 5800 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5801 5802 Level: beginner 5803 5804 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5805 @*/ 5806 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5807 { 5808 static PetscInt inassm = 0; 5809 PetscBool flg = PETSC_FALSE; 5810 5811 PetscFunctionBegin; 5812 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5813 PetscValidType(mat, 1); 5814 5815 inassm++; 5816 MatAssemblyEnd_InUse++; 5817 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5818 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5819 PetscTryTypeMethod(mat, assemblyend, type); 5820 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5821 } else PetscTryTypeMethod(mat, assemblyend, type); 5822 5823 /* Flush assembly is not a true assembly */ 5824 if (type != MAT_FLUSH_ASSEMBLY) { 5825 if (mat->num_ass) { 5826 if (!mat->symmetry_eternal) { 5827 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5828 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5829 } 5830 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5831 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5832 } 5833 mat->num_ass++; 5834 mat->assembled = PETSC_TRUE; 5835 mat->ass_nonzerostate = mat->nonzerostate; 5836 } 5837 5838 mat->insertmode = NOT_SET_VALUES; 5839 MatAssemblyEnd_InUse--; 5840 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5841 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5842 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5843 5844 if (mat->checksymmetryonassembly) { 5845 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5846 if (flg) { 5847 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5848 } else { 5849 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5850 } 5851 } 5852 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5853 } 5854 inassm--; 5855 PetscFunctionReturn(PETSC_SUCCESS); 5856 } 5857 5858 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5859 /*@ 5860 MatSetOption - Sets a parameter option for a matrix. Some options 5861 may be specific to certain storage formats. Some options 5862 determine how values will be inserted (or added). Sorted, 5863 row-oriented input will generally assemble the fastest. The default 5864 is row-oriented. 5865 5866 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5867 5868 Input Parameters: 5869 + mat - the matrix 5870 . op - the option, one of those listed below (and possibly others), 5871 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5872 5873 Options Describing Matrix Structure: 5874 + `MAT_SPD` - symmetric positive definite 5875 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5876 . `MAT_HERMITIAN` - transpose is the complex conjugation 5877 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5878 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5879 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5880 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5881 5882 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5883 do not need to be computed (usually at a high cost) 5884 5885 Options For Use with `MatSetValues()`: 5886 Insert a logically dense subblock, which can be 5887 . `MAT_ROW_ORIENTED` - row-oriented (default) 5888 5889 These options reflect the data you pass in with `MatSetValues()`; it has 5890 nothing to do with how the data is stored internally in the matrix 5891 data structure. 5892 5893 When (re)assembling a matrix, we can restrict the input for 5894 efficiency/debugging purposes. These options include 5895 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5896 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5897 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5898 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5899 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5900 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5901 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5902 performance for very large process counts. 5903 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5904 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5905 functions, instead sending only neighbor messages. 5906 5907 Level: intermediate 5908 5909 Notes: 5910 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5911 5912 Some options are relevant only for particular matrix types and 5913 are thus ignored by others. Other options are not supported by 5914 certain matrix types and will generate an error message if set. 5915 5916 If using Fortran to compute a matrix, one may need to 5917 use the column-oriented option (or convert to the row-oriented 5918 format). 5919 5920 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5921 that would generate a new entry in the nonzero structure is instead 5922 ignored. Thus, if memory has not already been allocated for this particular 5923 data, then the insertion is ignored. For dense matrices, in which 5924 the entire array is allocated, no entries are ever ignored. 5925 Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5926 5927 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5928 that would generate a new entry in the nonzero structure instead produces 5929 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 5930 5931 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5932 that would generate a new entry that has not been preallocated will 5933 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5934 only.) This is a useful flag when debugging matrix memory preallocation. 5935 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5936 5937 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5938 other processors should be dropped, rather than stashed. 5939 This is useful if you know that the "owning" processor is also 5940 always generating the correct matrix entries, so that PETSc need 5941 not transfer duplicate entries generated on another processor. 5942 5943 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5944 searches during matrix assembly. When this flag is set, the hash table 5945 is created during the first matrix assembly. This hash table is 5946 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5947 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5948 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5949 supported by `MATMPIBAIJ` format only. 5950 5951 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5952 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 5953 5954 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5955 a zero location in the matrix 5956 5957 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5958 5959 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5960 zero row routines and thus improves performance for very large process counts. 5961 5962 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5963 part of the matrix (since they should match the upper triangular part). 5964 5965 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5966 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 5967 with finite difference schemes with non-periodic boundary conditions. 5968 5969 Developer Note: 5970 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5971 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 5972 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5973 not changed. 5974 5975 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5976 @*/ 5977 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5978 { 5979 PetscFunctionBegin; 5980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5981 if (op > 0) { 5982 PetscValidLogicalCollectiveEnum(mat, op, 2); 5983 PetscValidLogicalCollectiveBool(mat, flg, 3); 5984 } 5985 5986 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); 5987 5988 switch (op) { 5989 case MAT_FORCE_DIAGONAL_ENTRIES: 5990 mat->force_diagonals = flg; 5991 PetscFunctionReturn(PETSC_SUCCESS); 5992 case MAT_NO_OFF_PROC_ENTRIES: 5993 mat->nooffprocentries = flg; 5994 PetscFunctionReturn(PETSC_SUCCESS); 5995 case MAT_SUBSET_OFF_PROC_ENTRIES: 5996 mat->assembly_subset = flg; 5997 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5998 #if !defined(PETSC_HAVE_MPIUNI) 5999 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6000 #endif 6001 mat->stash.first_assembly_done = PETSC_FALSE; 6002 } 6003 PetscFunctionReturn(PETSC_SUCCESS); 6004 case MAT_NO_OFF_PROC_ZERO_ROWS: 6005 mat->nooffproczerorows = flg; 6006 PetscFunctionReturn(PETSC_SUCCESS); 6007 case MAT_SPD: 6008 if (flg) { 6009 mat->spd = PETSC_BOOL3_TRUE; 6010 mat->symmetric = PETSC_BOOL3_TRUE; 6011 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6012 } else { 6013 mat->spd = PETSC_BOOL3_FALSE; 6014 } 6015 break; 6016 case MAT_SYMMETRIC: 6017 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6018 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6019 #if !defined(PETSC_USE_COMPLEX) 6020 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6021 #endif 6022 break; 6023 case MAT_HERMITIAN: 6024 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6025 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6026 #if !defined(PETSC_USE_COMPLEX) 6027 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6028 #endif 6029 break; 6030 case MAT_STRUCTURALLY_SYMMETRIC: 6031 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6032 break; 6033 case MAT_SYMMETRY_ETERNAL: 6034 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"); 6035 mat->symmetry_eternal = flg; 6036 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6037 break; 6038 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6039 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"); 6040 mat->structural_symmetry_eternal = flg; 6041 break; 6042 case MAT_SPD_ETERNAL: 6043 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"); 6044 mat->spd_eternal = flg; 6045 if (flg) { 6046 mat->structural_symmetry_eternal = PETSC_TRUE; 6047 mat->symmetry_eternal = PETSC_TRUE; 6048 } 6049 break; 6050 case MAT_STRUCTURE_ONLY: 6051 mat->structure_only = flg; 6052 break; 6053 case MAT_SORTED_FULL: 6054 mat->sortedfull = flg; 6055 break; 6056 default: 6057 break; 6058 } 6059 PetscTryTypeMethod(mat, setoption, op, flg); 6060 PetscFunctionReturn(PETSC_SUCCESS); 6061 } 6062 6063 /*@ 6064 MatGetOption - Gets a parameter option that has been set for a matrix. 6065 6066 Logically Collective 6067 6068 Input Parameters: 6069 + mat - the matrix 6070 - op - the option, this only responds to certain options, check the code for which ones 6071 6072 Output Parameter: 6073 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6074 6075 Level: intermediate 6076 6077 Notes: 6078 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6079 6080 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6081 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6082 6083 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6084 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6085 @*/ 6086 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6087 { 6088 PetscFunctionBegin; 6089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6090 PetscValidType(mat, 1); 6091 6092 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); 6093 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()"); 6094 6095 switch (op) { 6096 case MAT_NO_OFF_PROC_ENTRIES: 6097 *flg = mat->nooffprocentries; 6098 break; 6099 case MAT_NO_OFF_PROC_ZERO_ROWS: 6100 *flg = mat->nooffproczerorows; 6101 break; 6102 case MAT_SYMMETRIC: 6103 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6104 break; 6105 case MAT_HERMITIAN: 6106 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6107 break; 6108 case MAT_STRUCTURALLY_SYMMETRIC: 6109 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6110 break; 6111 case MAT_SPD: 6112 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6113 break; 6114 case MAT_SYMMETRY_ETERNAL: 6115 *flg = mat->symmetry_eternal; 6116 break; 6117 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6118 *flg = mat->symmetry_eternal; 6119 break; 6120 default: 6121 break; 6122 } 6123 PetscFunctionReturn(PETSC_SUCCESS); 6124 } 6125 6126 /*@ 6127 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6128 this routine retains the old nonzero structure. 6129 6130 Logically Collective 6131 6132 Input Parameter: 6133 . mat - the matrix 6134 6135 Level: intermediate 6136 6137 Note: 6138 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. 6139 See the Performance chapter of the users manual for information on preallocating matrices. 6140 6141 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6142 @*/ 6143 PetscErrorCode MatZeroEntries(Mat mat) 6144 { 6145 PetscFunctionBegin; 6146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6147 PetscValidType(mat, 1); 6148 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6149 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"); 6150 MatCheckPreallocated(mat, 1); 6151 6152 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6153 PetscUseTypeMethod(mat, zeroentries); 6154 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6155 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6156 PetscFunctionReturn(PETSC_SUCCESS); 6157 } 6158 6159 /*@ 6160 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6161 of a set of rows and columns of a matrix. 6162 6163 Collective 6164 6165 Input Parameters: 6166 + mat - the matrix 6167 . numRows - the number of rows/columns to zero 6168 . rows - the global row indices 6169 . diag - value put in the diagonal of the eliminated rows 6170 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6171 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6172 6173 Level: intermediate 6174 6175 Notes: 6176 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6177 6178 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6179 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 6180 6181 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6182 Krylov method to take advantage of the known solution on the zeroed rows. 6183 6184 For the parallel case, all processes that share the matrix (i.e., 6185 those in the communicator used for matrix creation) MUST call this 6186 routine, regardless of whether any rows being zeroed are owned by 6187 them. 6188 6189 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6190 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 6191 missing. 6192 6193 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6194 list only rows local to itself). 6195 6196 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6197 6198 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6199 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6200 @*/ 6201 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6202 { 6203 PetscFunctionBegin; 6204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6205 PetscValidType(mat, 1); 6206 if (numRows) PetscAssertPointer(rows, 3); 6207 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6208 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6209 MatCheckPreallocated(mat, 1); 6210 6211 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6212 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6214 PetscFunctionReturn(PETSC_SUCCESS); 6215 } 6216 6217 /*@ 6218 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6219 of a set of rows and columns of a matrix. 6220 6221 Collective 6222 6223 Input Parameters: 6224 + mat - the matrix 6225 . is - the rows to zero 6226 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6227 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6228 - b - optional vector of right-hand side, that will be adjusted by provided solution 6229 6230 Level: intermediate 6231 6232 Note: 6233 See `MatZeroRowsColumns()` for details on how this routine operates. 6234 6235 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6236 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6237 @*/ 6238 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6239 { 6240 PetscInt numRows; 6241 const PetscInt *rows; 6242 6243 PetscFunctionBegin; 6244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6245 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6246 PetscValidType(mat, 1); 6247 PetscValidType(is, 2); 6248 PetscCall(ISGetLocalSize(is, &numRows)); 6249 PetscCall(ISGetIndices(is, &rows)); 6250 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6251 PetscCall(ISRestoreIndices(is, &rows)); 6252 PetscFunctionReturn(PETSC_SUCCESS); 6253 } 6254 6255 /*@ 6256 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6257 of a set of rows of a matrix. 6258 6259 Collective 6260 6261 Input Parameters: 6262 + mat - the matrix 6263 . numRows - the number of rows to zero 6264 . rows - the global row indices 6265 . diag - value put in the diagonal of the zeroed rows 6266 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6267 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6268 6269 Level: intermediate 6270 6271 Notes: 6272 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6273 6274 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6275 6276 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6277 Krylov method to take advantage of the known solution on the zeroed rows. 6278 6279 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) 6280 from the matrix. 6281 6282 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6283 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 6284 formats this does not alter the nonzero structure. 6285 6286 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6287 of the matrix is not changed the values are 6288 merely zeroed. 6289 6290 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6291 formats can optionally remove the main diagonal entry from the 6292 nonzero structure as well, by passing 0.0 as the final argument). 6293 6294 For the parallel case, all processes that share the matrix (i.e., 6295 those in the communicator used for matrix creation) MUST call this 6296 routine, regardless of whether any rows being zeroed are owned by 6297 them. 6298 6299 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6300 list only rows local to itself). 6301 6302 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6303 owns that are to be zeroed. This saves a global synchronization in the implementation. 6304 6305 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6306 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6307 @*/ 6308 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6309 { 6310 PetscFunctionBegin; 6311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6312 PetscValidType(mat, 1); 6313 if (numRows) PetscAssertPointer(rows, 3); 6314 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6315 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6316 MatCheckPreallocated(mat, 1); 6317 6318 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6319 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6320 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6321 PetscFunctionReturn(PETSC_SUCCESS); 6322 } 6323 6324 /*@ 6325 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6326 of a set of rows of a matrix. 6327 6328 Collective 6329 6330 Input Parameters: 6331 + mat - the matrix 6332 . is - index set of rows to remove (if `NULL` then no row is removed) 6333 . diag - value put in all diagonals of eliminated rows 6334 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6335 - b - optional vector of right-hand side, that will be adjusted by provided solution 6336 6337 Level: intermediate 6338 6339 Note: 6340 See `MatZeroRows()` for details on how this routine operates. 6341 6342 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6343 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6344 @*/ 6345 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6346 { 6347 PetscInt numRows = 0; 6348 const PetscInt *rows = NULL; 6349 6350 PetscFunctionBegin; 6351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6352 PetscValidType(mat, 1); 6353 if (is) { 6354 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6355 PetscCall(ISGetLocalSize(is, &numRows)); 6356 PetscCall(ISGetIndices(is, &rows)); 6357 } 6358 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6359 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6360 PetscFunctionReturn(PETSC_SUCCESS); 6361 } 6362 6363 /*@ 6364 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6365 of a set of rows of a matrix. These rows must be local to the process. 6366 6367 Collective 6368 6369 Input Parameters: 6370 + mat - the matrix 6371 . numRows - the number of rows to remove 6372 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6373 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6374 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6375 - b - optional vector of right-hand side, that will be adjusted by provided solution 6376 6377 Level: intermediate 6378 6379 Notes: 6380 See `MatZeroRows()` for details on how this routine operates. 6381 6382 The grid coordinates are across the entire grid, not just the local portion 6383 6384 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6385 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6386 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6387 `DM_BOUNDARY_PERIODIC` boundary type. 6388 6389 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 6390 a single value per point) you can skip filling those indices. 6391 6392 Fortran Note: 6393 `idxm` and `idxn` should be declared as 6394 $ MatStencil idxm(4, m) 6395 and the values inserted using 6396 .vb 6397 idxm(MatStencil_i, 1) = i 6398 idxm(MatStencil_j, 1) = j 6399 idxm(MatStencil_k, 1) = k 6400 idxm(MatStencil_c, 1) = c 6401 etc 6402 .ve 6403 6404 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6405 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6406 @*/ 6407 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6408 { 6409 PetscInt dim = mat->stencil.dim; 6410 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6411 PetscInt *dims = mat->stencil.dims + 1; 6412 PetscInt *starts = mat->stencil.starts; 6413 PetscInt *dxm = (PetscInt *)rows; 6414 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6415 6416 PetscFunctionBegin; 6417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6418 PetscValidType(mat, 1); 6419 if (numRows) PetscAssertPointer(rows, 3); 6420 6421 PetscCall(PetscMalloc1(numRows, &jdxm)); 6422 for (i = 0; i < numRows; ++i) { 6423 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6424 for (j = 0; j < 3 - sdim; ++j) dxm++; 6425 /* Local index in X dir */ 6426 tmp = *dxm++ - starts[0]; 6427 /* Loop over remaining dimensions */ 6428 for (j = 0; j < dim - 1; ++j) { 6429 /* If nonlocal, set index to be negative */ 6430 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6431 /* Update local index */ 6432 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6433 } 6434 /* Skip component slot if necessary */ 6435 if (mat->stencil.noc) dxm++; 6436 /* Local row number */ 6437 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6438 } 6439 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6440 PetscCall(PetscFree(jdxm)); 6441 PetscFunctionReturn(PETSC_SUCCESS); 6442 } 6443 6444 /*@ 6445 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6446 of a set of rows and columns of a matrix. 6447 6448 Collective 6449 6450 Input Parameters: 6451 + mat - the matrix 6452 . numRows - the number of rows/columns to remove 6453 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6454 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6455 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6456 - b - optional vector of right-hand side, that will be adjusted by provided solution 6457 6458 Level: intermediate 6459 6460 Notes: 6461 See `MatZeroRowsColumns()` for details on how this routine operates. 6462 6463 The grid coordinates are across the entire grid, not just the local portion 6464 6465 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6466 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6467 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6468 `DM_BOUNDARY_PERIODIC` boundary type. 6469 6470 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 6471 a single value per point) you can skip filling those indices. 6472 6473 Fortran Note: 6474 `idxm` and `idxn` should be declared as 6475 $ MatStencil idxm(4, m) 6476 and the values inserted using 6477 .vb 6478 idxm(MatStencil_i, 1) = i 6479 idxm(MatStencil_j, 1) = j 6480 idxm(MatStencil_k, 1) = k 6481 idxm(MatStencil_c, 1) = c 6482 etc 6483 .ve 6484 6485 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6486 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6487 @*/ 6488 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6489 { 6490 PetscInt dim = mat->stencil.dim; 6491 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6492 PetscInt *dims = mat->stencil.dims + 1; 6493 PetscInt *starts = mat->stencil.starts; 6494 PetscInt *dxm = (PetscInt *)rows; 6495 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6496 6497 PetscFunctionBegin; 6498 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6499 PetscValidType(mat, 1); 6500 if (numRows) PetscAssertPointer(rows, 3); 6501 6502 PetscCall(PetscMalloc1(numRows, &jdxm)); 6503 for (i = 0; i < numRows; ++i) { 6504 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6505 for (j = 0; j < 3 - sdim; ++j) dxm++; 6506 /* Local index in X dir */ 6507 tmp = *dxm++ - starts[0]; 6508 /* Loop over remaining dimensions */ 6509 for (j = 0; j < dim - 1; ++j) { 6510 /* If nonlocal, set index to be negative */ 6511 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6512 /* Update local index */ 6513 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6514 } 6515 /* Skip component slot if necessary */ 6516 if (mat->stencil.noc) dxm++; 6517 /* Local row number */ 6518 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6519 } 6520 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6521 PetscCall(PetscFree(jdxm)); 6522 PetscFunctionReturn(PETSC_SUCCESS); 6523 } 6524 6525 /*@C 6526 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6527 of a set of rows of a matrix; using local numbering of rows. 6528 6529 Collective 6530 6531 Input Parameters: 6532 + mat - the matrix 6533 . numRows - the number of rows to remove 6534 . rows - the local row indices 6535 . diag - value put in all diagonals of eliminated rows 6536 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6537 - b - optional vector of right-hand side, that will be adjusted by provided solution 6538 6539 Level: intermediate 6540 6541 Notes: 6542 Before calling `MatZeroRowsLocal()`, the user must first set the 6543 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6544 6545 See `MatZeroRows()` for details on how this routine operates. 6546 6547 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6548 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6549 @*/ 6550 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6551 { 6552 PetscFunctionBegin; 6553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6554 PetscValidType(mat, 1); 6555 if (numRows) PetscAssertPointer(rows, 3); 6556 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6557 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6558 MatCheckPreallocated(mat, 1); 6559 6560 if (mat->ops->zerorowslocal) { 6561 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6562 } else { 6563 IS is, newis; 6564 const PetscInt *newRows; 6565 6566 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6567 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6568 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6569 PetscCall(ISGetIndices(newis, &newRows)); 6570 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6571 PetscCall(ISRestoreIndices(newis, &newRows)); 6572 PetscCall(ISDestroy(&newis)); 6573 PetscCall(ISDestroy(&is)); 6574 } 6575 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6576 PetscFunctionReturn(PETSC_SUCCESS); 6577 } 6578 6579 /*@ 6580 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6581 of a set of rows of a matrix; using local numbering of rows. 6582 6583 Collective 6584 6585 Input Parameters: 6586 + mat - the matrix 6587 . is - index set of rows to remove 6588 . diag - value put in all diagonals of eliminated rows 6589 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6590 - b - optional vector of right-hand side, that will be adjusted by provided solution 6591 6592 Level: intermediate 6593 6594 Notes: 6595 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6596 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6597 6598 See `MatZeroRows()` for details on how this routine operates. 6599 6600 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6601 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6602 @*/ 6603 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6604 { 6605 PetscInt numRows; 6606 const PetscInt *rows; 6607 6608 PetscFunctionBegin; 6609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6610 PetscValidType(mat, 1); 6611 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6612 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6613 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6614 MatCheckPreallocated(mat, 1); 6615 6616 PetscCall(ISGetLocalSize(is, &numRows)); 6617 PetscCall(ISGetIndices(is, &rows)); 6618 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6619 PetscCall(ISRestoreIndices(is, &rows)); 6620 PetscFunctionReturn(PETSC_SUCCESS); 6621 } 6622 6623 /*@ 6624 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6625 of a set of rows and columns of a matrix; using local numbering of rows. 6626 6627 Collective 6628 6629 Input Parameters: 6630 + mat - the matrix 6631 . numRows - the number of rows to remove 6632 . rows - the global row indices 6633 . diag - value put in all diagonals of eliminated rows 6634 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6635 - b - optional vector of right-hand side, that will be adjusted by provided solution 6636 6637 Level: intermediate 6638 6639 Notes: 6640 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6641 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6642 6643 See `MatZeroRowsColumns()` for details on how this routine operates. 6644 6645 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6646 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6647 @*/ 6648 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6649 { 6650 IS is, newis; 6651 const PetscInt *newRows; 6652 6653 PetscFunctionBegin; 6654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6655 PetscValidType(mat, 1); 6656 if (numRows) PetscAssertPointer(rows, 3); 6657 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6658 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6659 MatCheckPreallocated(mat, 1); 6660 6661 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6662 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6663 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6664 PetscCall(ISGetIndices(newis, &newRows)); 6665 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6666 PetscCall(ISRestoreIndices(newis, &newRows)); 6667 PetscCall(ISDestroy(&newis)); 6668 PetscCall(ISDestroy(&is)); 6669 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6670 PetscFunctionReturn(PETSC_SUCCESS); 6671 } 6672 6673 /*@ 6674 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6675 of a set of rows and columns of a matrix; using local numbering of rows. 6676 6677 Collective 6678 6679 Input Parameters: 6680 + mat - the matrix 6681 . is - index set of rows to remove 6682 . diag - value put in all diagonals of eliminated rows 6683 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6684 - b - optional vector of right-hand side, that will be adjusted by provided solution 6685 6686 Level: intermediate 6687 6688 Notes: 6689 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6690 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6691 6692 See `MatZeroRowsColumns()` for details on how this routine operates. 6693 6694 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6695 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6696 @*/ 6697 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6698 { 6699 PetscInt numRows; 6700 const PetscInt *rows; 6701 6702 PetscFunctionBegin; 6703 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6704 PetscValidType(mat, 1); 6705 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6706 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6707 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6708 MatCheckPreallocated(mat, 1); 6709 6710 PetscCall(ISGetLocalSize(is, &numRows)); 6711 PetscCall(ISGetIndices(is, &rows)); 6712 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6713 PetscCall(ISRestoreIndices(is, &rows)); 6714 PetscFunctionReturn(PETSC_SUCCESS); 6715 } 6716 6717 /*@C 6718 MatGetSize - Returns the numbers of rows and columns in a matrix. 6719 6720 Not Collective 6721 6722 Input Parameter: 6723 . mat - the matrix 6724 6725 Output Parameters: 6726 + m - the number of global rows 6727 - n - the number of global columns 6728 6729 Level: beginner 6730 6731 Note: 6732 Both output parameters can be `NULL` on input. 6733 6734 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6735 @*/ 6736 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6737 { 6738 PetscFunctionBegin; 6739 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6740 if (m) *m = mat->rmap->N; 6741 if (n) *n = mat->cmap->N; 6742 PetscFunctionReturn(PETSC_SUCCESS); 6743 } 6744 6745 /*@C 6746 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6747 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6748 6749 Not Collective 6750 6751 Input Parameter: 6752 . mat - the matrix 6753 6754 Output Parameters: 6755 + m - the number of local rows, use `NULL` to not obtain this value 6756 - n - the number of local columns, use `NULL` to not obtain this value 6757 6758 Level: beginner 6759 6760 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6761 @*/ 6762 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6763 { 6764 PetscFunctionBegin; 6765 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6766 if (m) PetscAssertPointer(m, 2); 6767 if (n) PetscAssertPointer(n, 3); 6768 if (m) *m = mat->rmap->n; 6769 if (n) *n = mat->cmap->n; 6770 PetscFunctionReturn(PETSC_SUCCESS); 6771 } 6772 6773 /*@C 6774 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6775 vector one multiplies this matrix by that are owned by this processor. 6776 6777 Not Collective, unless matrix has not been allocated, then collective 6778 6779 Input Parameter: 6780 . mat - the matrix 6781 6782 Output Parameters: 6783 + m - the global index of the first local column, use `NULL` to not obtain this value 6784 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6785 6786 Level: developer 6787 6788 Note: 6789 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6790 Layouts](sec_matlayout) for details on matrix layouts. 6791 6792 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6793 @*/ 6794 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6795 { 6796 PetscFunctionBegin; 6797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6798 PetscValidType(mat, 1); 6799 if (m) PetscAssertPointer(m, 2); 6800 if (n) PetscAssertPointer(n, 3); 6801 MatCheckPreallocated(mat, 1); 6802 if (m) *m = mat->cmap->rstart; 6803 if (n) *n = mat->cmap->rend; 6804 PetscFunctionReturn(PETSC_SUCCESS); 6805 } 6806 6807 /*@C 6808 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6809 this MPI process. 6810 6811 Not Collective 6812 6813 Input Parameter: 6814 . mat - the matrix 6815 6816 Output Parameters: 6817 + m - the global index of the first local row, use `NULL` to not obtain this value 6818 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6819 6820 Level: beginner 6821 6822 Note: 6823 For all matrices it returns the range of matrix rows associated with rows of a vector that 6824 would contain the result of a matrix vector product with this matrix. See [Matrix 6825 Layouts](sec_matlayout) for details on matrix layouts. 6826 6827 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6828 `PetscLayout` 6829 @*/ 6830 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6831 { 6832 PetscFunctionBegin; 6833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6834 PetscValidType(mat, 1); 6835 if (m) PetscAssertPointer(m, 2); 6836 if (n) PetscAssertPointer(n, 3); 6837 MatCheckPreallocated(mat, 1); 6838 if (m) *m = mat->rmap->rstart; 6839 if (n) *n = mat->rmap->rend; 6840 PetscFunctionReturn(PETSC_SUCCESS); 6841 } 6842 6843 /*@C 6844 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6845 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6846 6847 Not Collective, unless matrix has not been allocated 6848 6849 Input Parameter: 6850 . mat - the matrix 6851 6852 Output Parameter: 6853 . ranges - start of each processors portion plus one more than the total length at the end 6854 6855 Level: beginner 6856 6857 Note: 6858 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6859 would contain the result of a matrix vector product with this matrix. See [Matrix 6860 Layouts](sec_matlayout) for details on matrix layouts. 6861 6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6863 @*/ 6864 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6865 { 6866 PetscFunctionBegin; 6867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6868 PetscValidType(mat, 1); 6869 MatCheckPreallocated(mat, 1); 6870 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6871 PetscFunctionReturn(PETSC_SUCCESS); 6872 } 6873 6874 /*@C 6875 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6876 vector one multiplies this vector by that are owned by each processor. 6877 6878 Not Collective, unless matrix has not been allocated 6879 6880 Input Parameter: 6881 . mat - the matrix 6882 6883 Output Parameter: 6884 . ranges - start of each processors portion plus one more than the total length at the end 6885 6886 Level: beginner 6887 6888 Note: 6889 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6890 Layouts](sec_matlayout) for details on matrix layouts. 6891 6892 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6893 @*/ 6894 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6895 { 6896 PetscFunctionBegin; 6897 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6898 PetscValidType(mat, 1); 6899 MatCheckPreallocated(mat, 1); 6900 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6901 PetscFunctionReturn(PETSC_SUCCESS); 6902 } 6903 6904 /*@C 6905 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6906 6907 Not Collective 6908 6909 Input Parameter: 6910 . A - matrix 6911 6912 Output Parameters: 6913 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6914 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6915 6916 Level: intermediate 6917 6918 Note: 6919 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6920 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6921 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6922 details on matrix layouts. 6923 6924 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6925 @*/ 6926 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6927 { 6928 PetscErrorCode (*f)(Mat, IS *, IS *); 6929 6930 PetscFunctionBegin; 6931 MatCheckPreallocated(A, 1); 6932 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6933 if (f) { 6934 PetscCall((*f)(A, rows, cols)); 6935 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6936 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6937 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6938 } 6939 PetscFunctionReturn(PETSC_SUCCESS); 6940 } 6941 6942 /*@C 6943 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6944 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6945 to complete the factorization. 6946 6947 Collective 6948 6949 Input Parameters: 6950 + fact - the factorized matrix obtained with `MatGetFactor()` 6951 . mat - the matrix 6952 . row - row permutation 6953 . col - column permutation 6954 - info - structure containing 6955 .vb 6956 levels - number of levels of fill. 6957 expected fill - as ratio of original fill. 6958 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6959 missing diagonal entries) 6960 .ve 6961 6962 Level: developer 6963 6964 Notes: 6965 See [Matrix Factorization](sec_matfactor) for additional information. 6966 6967 Most users should employ the `KSP` interface for linear solvers 6968 instead of working directly with matrix algebra routines such as this. 6969 See, e.g., `KSPCreate()`. 6970 6971 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 6972 6973 Developer Note: 6974 The Fortran interface is not autogenerated as the 6975 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6976 6977 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6978 `MatGetOrdering()`, `MatFactorInfo` 6979 @*/ 6980 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6981 { 6982 PetscFunctionBegin; 6983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6984 PetscValidType(mat, 2); 6985 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6986 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6987 PetscAssertPointer(info, 5); 6988 PetscAssertPointer(fact, 1); 6989 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6990 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6991 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6992 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6993 MatCheckPreallocated(mat, 2); 6994 6995 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6996 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6997 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6998 PetscFunctionReturn(PETSC_SUCCESS); 6999 } 7000 7001 /*@C 7002 MatICCFactorSymbolic - Performs symbolic incomplete 7003 Cholesky factorization for a symmetric matrix. Use 7004 `MatCholeskyFactorNumeric()` to complete the factorization. 7005 7006 Collective 7007 7008 Input Parameters: 7009 + fact - the factorized matrix obtained with `MatGetFactor()` 7010 . mat - the matrix to be factored 7011 . perm - row and column permutation 7012 - info - structure containing 7013 .vb 7014 levels - number of levels of fill. 7015 expected fill - as ratio of original fill. 7016 .ve 7017 7018 Level: developer 7019 7020 Notes: 7021 Most users should employ the `KSP` interface for linear solvers 7022 instead of working directly with matrix algebra routines such as this. 7023 See, e.g., `KSPCreate()`. 7024 7025 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7026 7027 Developer Note: 7028 The Fortran interface is not autogenerated as the 7029 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7030 7031 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7032 @*/ 7033 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7034 { 7035 PetscFunctionBegin; 7036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7037 PetscValidType(mat, 2); 7038 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7039 PetscAssertPointer(info, 4); 7040 PetscAssertPointer(fact, 1); 7041 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7042 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7043 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7044 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7045 MatCheckPreallocated(mat, 2); 7046 7047 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7048 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7049 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7050 PetscFunctionReturn(PETSC_SUCCESS); 7051 } 7052 7053 /*@C 7054 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7055 points to an array of valid matrices, they may be reused to store the new 7056 submatrices. 7057 7058 Collective 7059 7060 Input Parameters: 7061 + mat - the matrix 7062 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7063 . irow - index set of rows to extract 7064 . icol - index set of columns to extract 7065 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7066 7067 Output Parameter: 7068 . submat - the array of submatrices 7069 7070 Level: advanced 7071 7072 Notes: 7073 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7074 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7075 to extract a parallel submatrix. 7076 7077 Some matrix types place restrictions on the row and column 7078 indices, such as that they be sorted or that they be equal to each other. 7079 7080 The index sets may not have duplicate entries. 7081 7082 When extracting submatrices from a parallel matrix, each processor can 7083 form a different submatrix by setting the rows and columns of its 7084 individual index sets according to the local submatrix desired. 7085 7086 When finished using the submatrices, the user should destroy 7087 them with `MatDestroySubMatrices()`. 7088 7089 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7090 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7091 7092 This routine creates the matrices in submat; you should NOT create them before 7093 calling it. It also allocates the array of matrix pointers submat. 7094 7095 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7096 request one row/column in a block, they must request all rows/columns that are in 7097 that block. For example, if the block size is 2 you cannot request just row 0 and 7098 column 0. 7099 7100 Fortran Note: 7101 The Fortran interface is slightly different from that given below; it 7102 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7103 7104 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7105 @*/ 7106 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7107 { 7108 PetscInt i; 7109 PetscBool eq; 7110 7111 PetscFunctionBegin; 7112 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7113 PetscValidType(mat, 1); 7114 if (n) { 7115 PetscAssertPointer(irow, 3); 7116 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7117 PetscAssertPointer(icol, 4); 7118 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7119 } 7120 PetscAssertPointer(submat, 6); 7121 if (n && scall == MAT_REUSE_MATRIX) { 7122 PetscAssertPointer(*submat, 6); 7123 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7124 } 7125 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7126 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7127 MatCheckPreallocated(mat, 1); 7128 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7129 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7130 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7131 for (i = 0; i < n; i++) { 7132 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7133 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7134 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7135 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7136 if (mat->boundtocpu && mat->bindingpropagates) { 7137 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7138 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7139 } 7140 #endif 7141 } 7142 PetscFunctionReturn(PETSC_SUCCESS); 7143 } 7144 7145 /*@C 7146 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7147 7148 Collective 7149 7150 Input Parameters: 7151 + mat - the matrix 7152 . n - the number of submatrixes to be extracted 7153 . irow - index set of rows to extract 7154 . icol - index set of columns to extract 7155 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7156 7157 Output Parameter: 7158 . submat - the array of submatrices 7159 7160 Level: advanced 7161 7162 Note: 7163 This is used by `PCGASM` 7164 7165 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7166 @*/ 7167 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7168 { 7169 PetscInt i; 7170 PetscBool eq; 7171 7172 PetscFunctionBegin; 7173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7174 PetscValidType(mat, 1); 7175 if (n) { 7176 PetscAssertPointer(irow, 3); 7177 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7178 PetscAssertPointer(icol, 4); 7179 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7180 } 7181 PetscAssertPointer(submat, 6); 7182 if (n && scall == MAT_REUSE_MATRIX) { 7183 PetscAssertPointer(*submat, 6); 7184 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7185 } 7186 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7187 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7188 MatCheckPreallocated(mat, 1); 7189 7190 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7191 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7192 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7193 for (i = 0; i < n; i++) { 7194 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7195 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7196 } 7197 PetscFunctionReturn(PETSC_SUCCESS); 7198 } 7199 7200 /*@C 7201 MatDestroyMatrices - Destroys an array of matrices. 7202 7203 Collective 7204 7205 Input Parameters: 7206 + n - the number of local matrices 7207 - mat - the matrices (this is a pointer to the array of matrices) 7208 7209 Level: advanced 7210 7211 Note: 7212 Frees not only the matrices, but also the array that contains the matrices 7213 7214 Fortran Note: 7215 This does not free the array. 7216 7217 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7218 @*/ 7219 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7220 { 7221 PetscInt i; 7222 7223 PetscFunctionBegin; 7224 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7225 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7226 PetscAssertPointer(mat, 2); 7227 7228 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7229 7230 /* memory is allocated even if n = 0 */ 7231 PetscCall(PetscFree(*mat)); 7232 PetscFunctionReturn(PETSC_SUCCESS); 7233 } 7234 7235 /*@C 7236 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7237 7238 Collective 7239 7240 Input Parameters: 7241 + n - the number of local matrices 7242 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7243 sequence of `MatCreateSubMatrices()`) 7244 7245 Level: advanced 7246 7247 Note: 7248 Frees not only the matrices, but also the array that contains the matrices 7249 7250 Fortran Note: 7251 This does not free the array. 7252 7253 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7254 @*/ 7255 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7256 { 7257 Mat mat0; 7258 7259 PetscFunctionBegin; 7260 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7261 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7262 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7263 PetscAssertPointer(mat, 2); 7264 7265 mat0 = (*mat)[0]; 7266 if (mat0 && mat0->ops->destroysubmatrices) { 7267 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7268 } else { 7269 PetscCall(MatDestroyMatrices(n, mat)); 7270 } 7271 PetscFunctionReturn(PETSC_SUCCESS); 7272 } 7273 7274 /*@C 7275 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7276 7277 Collective 7278 7279 Input Parameter: 7280 . mat - the matrix 7281 7282 Output Parameter: 7283 . matstruct - the sequential matrix with the nonzero structure of mat 7284 7285 Level: developer 7286 7287 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7288 @*/ 7289 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7290 { 7291 PetscFunctionBegin; 7292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7293 PetscAssertPointer(matstruct, 2); 7294 7295 PetscValidType(mat, 1); 7296 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7297 MatCheckPreallocated(mat, 1); 7298 7299 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7300 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7301 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7302 PetscFunctionReturn(PETSC_SUCCESS); 7303 } 7304 7305 /*@C 7306 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7307 7308 Collective 7309 7310 Input Parameter: 7311 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7312 sequence of `MatGetSeqNonzeroStructure()`) 7313 7314 Level: advanced 7315 7316 Note: 7317 Frees not only the matrices, but also the array that contains the matrices 7318 7319 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7320 @*/ 7321 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7322 { 7323 PetscFunctionBegin; 7324 PetscAssertPointer(mat, 1); 7325 PetscCall(MatDestroy(mat)); 7326 PetscFunctionReturn(PETSC_SUCCESS); 7327 } 7328 7329 /*@ 7330 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7331 replaces the index sets by larger ones that represent submatrices with 7332 additional overlap. 7333 7334 Collective 7335 7336 Input Parameters: 7337 + mat - the matrix 7338 . n - the number of index sets 7339 . is - the array of index sets (these index sets will changed during the call) 7340 - ov - the additional overlap requested 7341 7342 Options Database Key: 7343 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7344 7345 Level: developer 7346 7347 Note: 7348 The computed overlap preserves the matrix block sizes when the blocks are square. 7349 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7350 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7351 7352 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7353 @*/ 7354 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7355 { 7356 PetscInt i, bs, cbs; 7357 7358 PetscFunctionBegin; 7359 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7360 PetscValidType(mat, 1); 7361 PetscValidLogicalCollectiveInt(mat, n, 2); 7362 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7363 if (n) { 7364 PetscAssertPointer(is, 3); 7365 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7366 } 7367 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7368 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7369 MatCheckPreallocated(mat, 1); 7370 7371 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7372 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7373 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7374 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7375 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7376 if (bs == cbs) { 7377 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7378 } 7379 PetscFunctionReturn(PETSC_SUCCESS); 7380 } 7381 7382 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7383 7384 /*@ 7385 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7386 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7387 additional overlap. 7388 7389 Collective 7390 7391 Input Parameters: 7392 + mat - the matrix 7393 . n - the number of index sets 7394 . is - the array of index sets (these index sets will changed during the call) 7395 - ov - the additional overlap requested 7396 7397 ` Options Database Key: 7398 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7399 7400 Level: developer 7401 7402 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7403 @*/ 7404 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7405 { 7406 PetscInt i; 7407 7408 PetscFunctionBegin; 7409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7410 PetscValidType(mat, 1); 7411 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7412 if (n) { 7413 PetscAssertPointer(is, 3); 7414 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7415 } 7416 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7417 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7418 MatCheckPreallocated(mat, 1); 7419 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7420 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7421 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7422 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7423 PetscFunctionReturn(PETSC_SUCCESS); 7424 } 7425 7426 /*@ 7427 MatGetBlockSize - Returns the matrix block size. 7428 7429 Not Collective 7430 7431 Input Parameter: 7432 . mat - the matrix 7433 7434 Output Parameter: 7435 . bs - block size 7436 7437 Level: intermediate 7438 7439 Notes: 7440 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7441 7442 If the block size has not been set yet this routine returns 1. 7443 7444 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7445 @*/ 7446 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7447 { 7448 PetscFunctionBegin; 7449 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7450 PetscAssertPointer(bs, 2); 7451 *bs = PetscAbs(mat->rmap->bs); 7452 PetscFunctionReturn(PETSC_SUCCESS); 7453 } 7454 7455 /*@ 7456 MatGetBlockSizes - Returns the matrix block row and column sizes. 7457 7458 Not Collective 7459 7460 Input Parameter: 7461 . mat - the matrix 7462 7463 Output Parameters: 7464 + rbs - row block size 7465 - cbs - column block size 7466 7467 Level: intermediate 7468 7469 Notes: 7470 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7471 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7472 7473 If a block size has not been set yet this routine returns 1. 7474 7475 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7476 @*/ 7477 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7478 { 7479 PetscFunctionBegin; 7480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7481 if (rbs) PetscAssertPointer(rbs, 2); 7482 if (cbs) PetscAssertPointer(cbs, 3); 7483 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7484 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7485 PetscFunctionReturn(PETSC_SUCCESS); 7486 } 7487 7488 /*@ 7489 MatSetBlockSize - Sets the matrix block size. 7490 7491 Logically Collective 7492 7493 Input Parameters: 7494 + mat - the matrix 7495 - bs - block size 7496 7497 Level: intermediate 7498 7499 Notes: 7500 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7501 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7502 7503 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7504 is compatible with the matrix local sizes. 7505 7506 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7507 @*/ 7508 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7509 { 7510 PetscFunctionBegin; 7511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7512 PetscValidLogicalCollectiveInt(mat, bs, 2); 7513 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7514 PetscFunctionReturn(PETSC_SUCCESS); 7515 } 7516 7517 typedef struct { 7518 PetscInt n; 7519 IS *is; 7520 Mat *mat; 7521 PetscObjectState nonzerostate; 7522 Mat C; 7523 } EnvelopeData; 7524 7525 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7526 { 7527 EnvelopeData *edata = (EnvelopeData *)ptr; 7528 7529 PetscFunctionBegin; 7530 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7531 PetscCall(PetscFree(edata->is)); 7532 PetscCall(PetscFree(edata)); 7533 PetscFunctionReturn(PETSC_SUCCESS); 7534 } 7535 7536 /*@ 7537 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7538 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7539 7540 Collective 7541 7542 Input Parameter: 7543 . mat - the matrix 7544 7545 Level: intermediate 7546 7547 Notes: 7548 There can be zeros within the blocks 7549 7550 The blocks can overlap between processes, including laying on more than two processes 7551 7552 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7553 @*/ 7554 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7555 { 7556 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7557 PetscInt *diag, *odiag, sc; 7558 VecScatter scatter; 7559 PetscScalar *seqv; 7560 const PetscScalar *parv; 7561 const PetscInt *ia, *ja; 7562 PetscBool set, flag, done; 7563 Mat AA = mat, A; 7564 MPI_Comm comm; 7565 PetscMPIInt rank, size, tag; 7566 MPI_Status status; 7567 PetscContainer container; 7568 EnvelopeData *edata; 7569 Vec seq, par; 7570 IS isglobal; 7571 7572 PetscFunctionBegin; 7573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7574 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7575 if (!set || !flag) { 7576 /* TODO: only needs nonzero structure of transpose */ 7577 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7578 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7579 } 7580 PetscCall(MatAIJGetLocalMat(AA, &A)); 7581 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7582 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7583 7584 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7585 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7586 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7587 PetscCallMPI(MPI_Comm_size(comm, &size)); 7588 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7589 7590 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7591 7592 if (rank > 0) { 7593 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7594 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7595 } 7596 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7597 for (i = 0; i < n; i++) { 7598 env = PetscMax(env, ja[ia[i + 1] - 1]); 7599 II = rstart + i; 7600 if (env == II) { 7601 starts[lblocks] = tbs; 7602 sizes[lblocks++] = 1 + II - tbs; 7603 tbs = 1 + II; 7604 } 7605 } 7606 if (rank < size - 1) { 7607 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7608 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7609 } 7610 7611 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7612 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7613 PetscCall(MatDestroy(&A)); 7614 7615 PetscCall(PetscNew(&edata)); 7616 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7617 edata->n = lblocks; 7618 /* create IS needed for extracting blocks from the original matrix */ 7619 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7620 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7621 7622 /* Create the resulting inverse matrix structure with preallocation information */ 7623 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7624 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7625 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7626 PetscCall(MatSetType(edata->C, MATAIJ)); 7627 7628 /* Communicate the start and end of each row, from each block to the correct rank */ 7629 /* TODO: Use PetscSF instead of VecScatter */ 7630 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7631 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7632 PetscCall(VecGetArrayWrite(seq, &seqv)); 7633 for (PetscInt i = 0; i < lblocks; i++) { 7634 for (PetscInt j = 0; j < sizes[i]; j++) { 7635 seqv[cnt] = starts[i]; 7636 seqv[cnt + 1] = starts[i] + sizes[i]; 7637 cnt += 2; 7638 } 7639 } 7640 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7641 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7642 sc -= cnt; 7643 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7644 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7645 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7646 PetscCall(ISDestroy(&isglobal)); 7647 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7648 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7649 PetscCall(VecScatterDestroy(&scatter)); 7650 PetscCall(VecDestroy(&seq)); 7651 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7652 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7653 PetscCall(VecGetArrayRead(par, &parv)); 7654 cnt = 0; 7655 PetscCall(MatGetSize(mat, NULL, &n)); 7656 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7657 PetscInt start, end, d = 0, od = 0; 7658 7659 start = (PetscInt)PetscRealPart(parv[cnt]); 7660 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7661 cnt += 2; 7662 7663 if (start < cstart) { 7664 od += cstart - start + n - cend; 7665 d += cend - cstart; 7666 } else if (start < cend) { 7667 od += n - cend; 7668 d += cend - start; 7669 } else od += n - start; 7670 if (end <= cstart) { 7671 od -= cstart - end + n - cend; 7672 d -= cend - cstart; 7673 } else if (end < cend) { 7674 od -= n - cend; 7675 d -= cend - end; 7676 } else od -= n - end; 7677 7678 odiag[i] = od; 7679 diag[i] = d; 7680 } 7681 PetscCall(VecRestoreArrayRead(par, &parv)); 7682 PetscCall(VecDestroy(&par)); 7683 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7684 PetscCall(PetscFree2(diag, odiag)); 7685 PetscCall(PetscFree2(sizes, starts)); 7686 7687 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7688 PetscCall(PetscContainerSetPointer(container, edata)); 7689 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7690 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7691 PetscCall(PetscObjectDereference((PetscObject)container)); 7692 PetscFunctionReturn(PETSC_SUCCESS); 7693 } 7694 7695 /*@ 7696 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7697 7698 Collective 7699 7700 Input Parameters: 7701 + A - the matrix 7702 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7703 7704 Output Parameter: 7705 . C - matrix with inverted block diagonal of `A` 7706 7707 Level: advanced 7708 7709 Note: 7710 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7711 7712 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7713 @*/ 7714 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7715 { 7716 PetscContainer container; 7717 EnvelopeData *edata; 7718 PetscObjectState nonzerostate; 7719 7720 PetscFunctionBegin; 7721 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7722 if (!container) { 7723 PetscCall(MatComputeVariableBlockEnvelope(A)); 7724 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7725 } 7726 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7727 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7728 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7729 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7730 7731 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7732 *C = edata->C; 7733 7734 for (PetscInt i = 0; i < edata->n; i++) { 7735 Mat D; 7736 PetscScalar *dvalues; 7737 7738 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7739 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7740 PetscCall(MatSeqDenseInvert(D)); 7741 PetscCall(MatDenseGetArray(D, &dvalues)); 7742 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7743 PetscCall(MatDestroy(&D)); 7744 } 7745 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7746 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7747 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7748 PetscFunctionReturn(PETSC_SUCCESS); 7749 } 7750 7751 /*@ 7752 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7753 7754 Logically Collective 7755 7756 Input Parameters: 7757 + mat - the matrix 7758 . nblocks - the number of blocks on this process, each block can only exist on a single process 7759 - bsizes - the block sizes 7760 7761 Level: intermediate 7762 7763 Notes: 7764 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7765 7766 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. 7767 7768 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7769 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7770 @*/ 7771 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7772 { 7773 PetscInt i, ncnt = 0, nlocal; 7774 7775 PetscFunctionBegin; 7776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7777 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7778 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); 7779 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7780 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); 7781 PetscCall(PetscFree(mat->bsizes)); 7782 mat->nblocks = nblocks; 7783 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7784 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7785 PetscFunctionReturn(PETSC_SUCCESS); 7786 } 7787 7788 /*@C 7789 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7790 7791 Logically Collective; No Fortran Support 7792 7793 Input Parameter: 7794 . mat - the matrix 7795 7796 Output Parameters: 7797 + nblocks - the number of blocks on this process 7798 - bsizes - the block sizes 7799 7800 Level: intermediate 7801 7802 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7803 @*/ 7804 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7805 { 7806 PetscFunctionBegin; 7807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7808 *nblocks = mat->nblocks; 7809 *bsizes = mat->bsizes; 7810 PetscFunctionReturn(PETSC_SUCCESS); 7811 } 7812 7813 /*@ 7814 MatSetBlockSizes - Sets the matrix block row and column sizes. 7815 7816 Logically Collective 7817 7818 Input Parameters: 7819 + mat - the matrix 7820 . rbs - row block size 7821 - cbs - column block size 7822 7823 Level: intermediate 7824 7825 Notes: 7826 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7827 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7828 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7829 7830 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7831 are compatible with the matrix local sizes. 7832 7833 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7834 7835 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7836 @*/ 7837 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7838 { 7839 PetscFunctionBegin; 7840 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7841 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7842 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7843 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7844 if (mat->rmap->refcnt) { 7845 ISLocalToGlobalMapping l2g = NULL; 7846 PetscLayout nmap = NULL; 7847 7848 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7849 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7850 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7851 mat->rmap = nmap; 7852 mat->rmap->mapping = l2g; 7853 } 7854 if (mat->cmap->refcnt) { 7855 ISLocalToGlobalMapping l2g = NULL; 7856 PetscLayout nmap = NULL; 7857 7858 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7859 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7860 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7861 mat->cmap = nmap; 7862 mat->cmap->mapping = l2g; 7863 } 7864 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7865 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7866 PetscFunctionReturn(PETSC_SUCCESS); 7867 } 7868 7869 /*@ 7870 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7871 7872 Logically Collective 7873 7874 Input Parameters: 7875 + mat - the matrix 7876 . fromRow - matrix from which to copy row block size 7877 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7878 7879 Level: developer 7880 7881 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7882 @*/ 7883 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7884 { 7885 PetscFunctionBegin; 7886 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7887 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7888 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7889 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7890 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7891 PetscFunctionReturn(PETSC_SUCCESS); 7892 } 7893 7894 /*@ 7895 MatResidual - Default routine to calculate the residual r = b - Ax 7896 7897 Collective 7898 7899 Input Parameters: 7900 + mat - the matrix 7901 . b - the right-hand-side 7902 - x - the approximate solution 7903 7904 Output Parameter: 7905 . r - location to store the residual 7906 7907 Level: developer 7908 7909 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7910 @*/ 7911 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7912 { 7913 PetscFunctionBegin; 7914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7915 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7916 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7917 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7918 PetscValidType(mat, 1); 7919 MatCheckPreallocated(mat, 1); 7920 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7921 if (!mat->ops->residual) { 7922 PetscCall(MatMult(mat, x, r)); 7923 PetscCall(VecAYPX(r, -1.0, b)); 7924 } else { 7925 PetscUseTypeMethod(mat, residual, b, x, r); 7926 } 7927 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7928 PetscFunctionReturn(PETSC_SUCCESS); 7929 } 7930 7931 /*MC 7932 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7933 7934 Synopsis: 7935 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7936 7937 Not Collective 7938 7939 Input Parameters: 7940 + A - the matrix 7941 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7942 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7943 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7944 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7945 always used. 7946 7947 Output Parameters: 7948 + n - number of local rows in the (possibly compressed) matrix 7949 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7950 . ja - the column indices 7951 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7952 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7953 7954 Level: developer 7955 7956 Note: 7957 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7958 7959 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7960 M*/ 7961 7962 /*MC 7963 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7964 7965 Synopsis: 7966 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7967 7968 Not Collective 7969 7970 Input Parameters: 7971 + A - the matrix 7972 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7973 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7974 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7975 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7976 always used. 7977 . n - number of local rows in the (possibly compressed) matrix 7978 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7979 . ja - the column indices 7980 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7981 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7982 7983 Level: developer 7984 7985 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7986 M*/ 7987 7988 /*@C 7989 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7990 7991 Collective 7992 7993 Input Parameters: 7994 + mat - the matrix 7995 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7996 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7997 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7998 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7999 always used. 8000 8001 Output Parameters: 8002 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8003 . 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 8004 . ja - the column indices, use `NULL` if not needed 8005 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8006 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8007 8008 Level: developer 8009 8010 Notes: 8011 You CANNOT change any of the ia[] or ja[] values. 8012 8013 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8014 8015 Fortran Notes: 8016 Use 8017 .vb 8018 PetscInt, pointer :: ia(:),ja(:) 8019 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8020 ! Access the ith and jth entries via ia(i) and ja(j) 8021 .ve 8022 8023 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8024 8025 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8026 @*/ 8027 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8028 { 8029 PetscFunctionBegin; 8030 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8031 PetscValidType(mat, 1); 8032 if (n) PetscAssertPointer(n, 5); 8033 if (ia) PetscAssertPointer(ia, 6); 8034 if (ja) PetscAssertPointer(ja, 7); 8035 if (done) PetscAssertPointer(done, 8); 8036 MatCheckPreallocated(mat, 1); 8037 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8038 else { 8039 if (done) *done = PETSC_TRUE; 8040 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8041 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8042 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8043 } 8044 PetscFunctionReturn(PETSC_SUCCESS); 8045 } 8046 8047 /*@C 8048 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8049 8050 Collective 8051 8052 Input Parameters: 8053 + mat - the matrix 8054 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8055 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8056 symmetrized 8057 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8058 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8059 always used. 8060 . n - number of columns in the (possibly compressed) matrix 8061 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8062 - ja - the row indices 8063 8064 Output Parameter: 8065 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8066 8067 Level: developer 8068 8069 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8070 @*/ 8071 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8072 { 8073 PetscFunctionBegin; 8074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8075 PetscValidType(mat, 1); 8076 PetscAssertPointer(n, 5); 8077 if (ia) PetscAssertPointer(ia, 6); 8078 if (ja) PetscAssertPointer(ja, 7); 8079 PetscAssertPointer(done, 8); 8080 MatCheckPreallocated(mat, 1); 8081 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8082 else { 8083 *done = PETSC_TRUE; 8084 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8085 } 8086 PetscFunctionReturn(PETSC_SUCCESS); 8087 } 8088 8089 /*@C 8090 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8091 8092 Collective 8093 8094 Input Parameters: 8095 + mat - the matrix 8096 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8097 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8098 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8099 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8100 always used. 8101 . n - size of (possibly compressed) matrix 8102 . ia - the row pointers 8103 - ja - the column indices 8104 8105 Output Parameter: 8106 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8107 8108 Level: developer 8109 8110 Note: 8111 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8112 us of the array after it has been restored. If you pass `NULL`, it will 8113 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8114 8115 Fortran Note: 8116 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8117 8118 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8119 @*/ 8120 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8121 { 8122 PetscFunctionBegin; 8123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8124 PetscValidType(mat, 1); 8125 if (ia) PetscAssertPointer(ia, 6); 8126 if (ja) PetscAssertPointer(ja, 7); 8127 if (done) PetscAssertPointer(done, 8); 8128 MatCheckPreallocated(mat, 1); 8129 8130 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8131 else { 8132 if (done) *done = PETSC_TRUE; 8133 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8134 if (n) *n = 0; 8135 if (ia) *ia = NULL; 8136 if (ja) *ja = NULL; 8137 } 8138 PetscFunctionReturn(PETSC_SUCCESS); 8139 } 8140 8141 /*@C 8142 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8143 8144 Collective 8145 8146 Input Parameters: 8147 + mat - the matrix 8148 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8149 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8150 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8151 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8152 always used. 8153 8154 Output Parameters: 8155 + n - size of (possibly compressed) matrix 8156 . ia - the column pointers 8157 . ja - the row indices 8158 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8159 8160 Level: developer 8161 8162 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8163 @*/ 8164 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8165 { 8166 PetscFunctionBegin; 8167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8168 PetscValidType(mat, 1); 8169 if (ia) PetscAssertPointer(ia, 6); 8170 if (ja) PetscAssertPointer(ja, 7); 8171 PetscAssertPointer(done, 8); 8172 MatCheckPreallocated(mat, 1); 8173 8174 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8175 else { 8176 *done = PETSC_TRUE; 8177 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8178 if (n) *n = 0; 8179 if (ia) *ia = NULL; 8180 if (ja) *ja = NULL; 8181 } 8182 PetscFunctionReturn(PETSC_SUCCESS); 8183 } 8184 8185 /*@C 8186 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8187 `MatGetColumnIJ()`. 8188 8189 Collective 8190 8191 Input Parameters: 8192 + mat - the matrix 8193 . ncolors - maximum color value 8194 . n - number of entries in colorarray 8195 - colorarray - array indicating color for each column 8196 8197 Output Parameter: 8198 . iscoloring - coloring generated using colorarray information 8199 8200 Level: developer 8201 8202 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8203 @*/ 8204 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8205 { 8206 PetscFunctionBegin; 8207 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8208 PetscValidType(mat, 1); 8209 PetscAssertPointer(colorarray, 4); 8210 PetscAssertPointer(iscoloring, 5); 8211 MatCheckPreallocated(mat, 1); 8212 8213 if (!mat->ops->coloringpatch) { 8214 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8215 } else { 8216 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8217 } 8218 PetscFunctionReturn(PETSC_SUCCESS); 8219 } 8220 8221 /*@ 8222 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8223 8224 Logically Collective 8225 8226 Input Parameter: 8227 . mat - the factored matrix to be reset 8228 8229 Level: developer 8230 8231 Notes: 8232 This routine should be used only with factored matrices formed by in-place 8233 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8234 format). This option can save memory, for example, when solving nonlinear 8235 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8236 ILU(0) preconditioner. 8237 8238 One can specify in-place ILU(0) factorization by calling 8239 .vb 8240 PCType(pc,PCILU); 8241 PCFactorSeUseInPlace(pc); 8242 .ve 8243 or by using the options -pc_type ilu -pc_factor_in_place 8244 8245 In-place factorization ILU(0) can also be used as a local 8246 solver for the blocks within the block Jacobi or additive Schwarz 8247 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8248 for details on setting local solver options. 8249 8250 Most users should employ the `KSP` interface for linear solvers 8251 instead of working directly with matrix algebra routines such as this. 8252 See, e.g., `KSPCreate()`. 8253 8254 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8255 @*/ 8256 PetscErrorCode MatSetUnfactored(Mat mat) 8257 { 8258 PetscFunctionBegin; 8259 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8260 PetscValidType(mat, 1); 8261 MatCheckPreallocated(mat, 1); 8262 mat->factortype = MAT_FACTOR_NONE; 8263 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8264 PetscUseTypeMethod(mat, setunfactored); 8265 PetscFunctionReturn(PETSC_SUCCESS); 8266 } 8267 8268 /*MC 8269 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8270 8271 Synopsis: 8272 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8273 8274 Not Collective 8275 8276 Input Parameter: 8277 . x - matrix 8278 8279 Output Parameters: 8280 + xx_v - the Fortran pointer to the array 8281 - ierr - error code 8282 8283 Example of Usage: 8284 .vb 8285 PetscScalar, pointer xx_v(:,:) 8286 .... 8287 call MatDenseGetArrayF90(x,xx_v,ierr) 8288 a = xx_v(3) 8289 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8290 .ve 8291 8292 Level: advanced 8293 8294 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8295 M*/ 8296 8297 /*MC 8298 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8299 accessed with `MatDenseGetArrayF90()`. 8300 8301 Synopsis: 8302 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8303 8304 Not Collective 8305 8306 Input Parameters: 8307 + x - matrix 8308 - xx_v - the Fortran90 pointer to the array 8309 8310 Output Parameter: 8311 . ierr - error code 8312 8313 Example of Usage: 8314 .vb 8315 PetscScalar, pointer xx_v(:,:) 8316 .... 8317 call MatDenseGetArrayF90(x,xx_v,ierr) 8318 a = xx_v(3) 8319 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8320 .ve 8321 8322 Level: advanced 8323 8324 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8325 M*/ 8326 8327 /*MC 8328 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8329 8330 Synopsis: 8331 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8332 8333 Not Collective 8334 8335 Input Parameter: 8336 . x - matrix 8337 8338 Output Parameters: 8339 + xx_v - the Fortran pointer to the array 8340 - ierr - error code 8341 8342 Example of Usage: 8343 .vb 8344 PetscScalar, pointer xx_v(:) 8345 .... 8346 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8347 a = xx_v(3) 8348 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8349 .ve 8350 8351 Level: advanced 8352 8353 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8354 M*/ 8355 8356 /*MC 8357 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8358 accessed with `MatSeqAIJGetArrayF90()`. 8359 8360 Synopsis: 8361 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8362 8363 Not Collective 8364 8365 Input Parameters: 8366 + x - matrix 8367 - xx_v - the Fortran90 pointer to the array 8368 8369 Output Parameter: 8370 . ierr - error code 8371 8372 Example of Usage: 8373 .vb 8374 PetscScalar, pointer xx_v(:) 8375 .... 8376 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8377 a = xx_v(3) 8378 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8379 .ve 8380 8381 Level: advanced 8382 8383 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8384 M*/ 8385 8386 /*@ 8387 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8388 as the original matrix. 8389 8390 Collective 8391 8392 Input Parameters: 8393 + mat - the original matrix 8394 . isrow - parallel `IS` containing the rows this processor should obtain 8395 . 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. 8396 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8397 8398 Output Parameter: 8399 . newmat - the new submatrix, of the same type as the original matrix 8400 8401 Level: advanced 8402 8403 Notes: 8404 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8405 8406 Some matrix types place restrictions on the row and column indices, such 8407 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; 8408 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8409 8410 The index sets may not have duplicate entries. 8411 8412 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8413 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8414 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8415 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8416 you are finished using it. 8417 8418 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8419 the input matrix. 8420 8421 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8422 8423 If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature 8424 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8425 8426 Example usage: 8427 Consider the following 8x8 matrix with 34 non-zero values, that is 8428 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8429 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8430 as follows 8431 .vb 8432 1 2 0 | 0 3 0 | 0 4 8433 Proc0 0 5 6 | 7 0 0 | 8 0 8434 9 0 10 | 11 0 0 | 12 0 8435 ------------------------------------- 8436 13 0 14 | 15 16 17 | 0 0 8437 Proc1 0 18 0 | 19 20 21 | 0 0 8438 0 0 0 | 22 23 0 | 24 0 8439 ------------------------------------- 8440 Proc2 25 26 27 | 0 0 28 | 29 0 8441 30 0 0 | 31 32 33 | 0 34 8442 .ve 8443 8444 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8445 8446 .vb 8447 2 0 | 0 3 0 | 0 8448 Proc0 5 6 | 7 0 0 | 8 8449 ------------------------------- 8450 Proc1 18 0 | 19 20 21 | 0 8451 ------------------------------- 8452 Proc2 26 27 | 0 0 28 | 29 8453 0 0 | 31 32 33 | 0 8454 .ve 8455 8456 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8457 @*/ 8458 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8459 { 8460 PetscMPIInt size; 8461 Mat *local; 8462 IS iscoltmp; 8463 PetscBool flg; 8464 8465 PetscFunctionBegin; 8466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8467 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8468 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8469 PetscAssertPointer(newmat, 5); 8470 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8471 PetscValidType(mat, 1); 8472 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8473 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8474 8475 MatCheckPreallocated(mat, 1); 8476 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8477 8478 if (!iscol || isrow == iscol) { 8479 PetscBool stride; 8480 PetscMPIInt grabentirematrix = 0, grab; 8481 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8482 if (stride) { 8483 PetscInt first, step, n, rstart, rend; 8484 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8485 if (step == 1) { 8486 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8487 if (rstart == first) { 8488 PetscCall(ISGetLocalSize(isrow, &n)); 8489 if (n == rend - rstart) grabentirematrix = 1; 8490 } 8491 } 8492 } 8493 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8494 if (grab) { 8495 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8496 if (cll == MAT_INITIAL_MATRIX) { 8497 *newmat = mat; 8498 PetscCall(PetscObjectReference((PetscObject)mat)); 8499 } 8500 PetscFunctionReturn(PETSC_SUCCESS); 8501 } 8502 } 8503 8504 if (!iscol) { 8505 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8506 } else { 8507 iscoltmp = iscol; 8508 } 8509 8510 /* if original matrix is on just one processor then use submatrix generated */ 8511 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8512 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8513 goto setproperties; 8514 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8515 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8516 *newmat = *local; 8517 PetscCall(PetscFree(local)); 8518 goto setproperties; 8519 } else if (!mat->ops->createsubmatrix) { 8520 /* Create a new matrix type that implements the operation using the full matrix */ 8521 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8522 switch (cll) { 8523 case MAT_INITIAL_MATRIX: 8524 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8525 break; 8526 case MAT_REUSE_MATRIX: 8527 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8528 break; 8529 default: 8530 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8531 } 8532 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8533 goto setproperties; 8534 } 8535 8536 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8537 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8538 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8539 8540 setproperties: 8541 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8542 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8543 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8544 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8545 PetscFunctionReturn(PETSC_SUCCESS); 8546 } 8547 8548 /*@ 8549 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8550 8551 Not Collective 8552 8553 Input Parameters: 8554 + A - the matrix we wish to propagate options from 8555 - B - the matrix we wish to propagate options to 8556 8557 Level: beginner 8558 8559 Note: 8560 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8561 8562 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8563 @*/ 8564 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8565 { 8566 PetscFunctionBegin; 8567 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8568 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8569 B->symmetry_eternal = A->symmetry_eternal; 8570 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8571 B->symmetric = A->symmetric; 8572 B->structurally_symmetric = A->structurally_symmetric; 8573 B->spd = A->spd; 8574 B->hermitian = A->hermitian; 8575 PetscFunctionReturn(PETSC_SUCCESS); 8576 } 8577 8578 /*@ 8579 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8580 used during the assembly process to store values that belong to 8581 other processors. 8582 8583 Not Collective 8584 8585 Input Parameters: 8586 + mat - the matrix 8587 . size - the initial size of the stash. 8588 - bsize - the initial size of the block-stash(if used). 8589 8590 Options Database Keys: 8591 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8592 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8593 8594 Level: intermediate 8595 8596 Notes: 8597 The block-stash is used for values set with `MatSetValuesBlocked()` while 8598 the stash is used for values set with `MatSetValues()` 8599 8600 Run with the option -info and look for output of the form 8601 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8602 to determine the appropriate value, MM, to use for size and 8603 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8604 to determine the value, BMM to use for bsize 8605 8606 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8607 @*/ 8608 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8609 { 8610 PetscFunctionBegin; 8611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8612 PetscValidType(mat, 1); 8613 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8614 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8615 PetscFunctionReturn(PETSC_SUCCESS); 8616 } 8617 8618 /*@ 8619 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8620 the matrix 8621 8622 Neighbor-wise Collective 8623 8624 Input Parameters: 8625 + A - the matrix 8626 . x - the vector to be multiplied by the interpolation operator 8627 - y - the vector to be added to the result 8628 8629 Output Parameter: 8630 . w - the resulting vector 8631 8632 Level: intermediate 8633 8634 Notes: 8635 `w` may be the same vector as `y`. 8636 8637 This allows one to use either the restriction or interpolation (its transpose) 8638 matrix to do the interpolation 8639 8640 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8641 @*/ 8642 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8643 { 8644 PetscInt M, N, Ny; 8645 8646 PetscFunctionBegin; 8647 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8648 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8649 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8650 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8651 PetscCall(MatGetSize(A, &M, &N)); 8652 PetscCall(VecGetSize(y, &Ny)); 8653 if (M == Ny) { 8654 PetscCall(MatMultAdd(A, x, y, w)); 8655 } else { 8656 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8657 } 8658 PetscFunctionReturn(PETSC_SUCCESS); 8659 } 8660 8661 /*@ 8662 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8663 the matrix 8664 8665 Neighbor-wise Collective 8666 8667 Input Parameters: 8668 + A - the matrix 8669 - x - the vector to be interpolated 8670 8671 Output Parameter: 8672 . y - the resulting vector 8673 8674 Level: intermediate 8675 8676 Note: 8677 This allows one to use either the restriction or interpolation (its transpose) 8678 matrix to do the interpolation 8679 8680 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8681 @*/ 8682 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8683 { 8684 PetscInt M, N, Ny; 8685 8686 PetscFunctionBegin; 8687 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8688 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8689 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8690 PetscCall(MatGetSize(A, &M, &N)); 8691 PetscCall(VecGetSize(y, &Ny)); 8692 if (M == Ny) { 8693 PetscCall(MatMult(A, x, y)); 8694 } else { 8695 PetscCall(MatMultTranspose(A, x, y)); 8696 } 8697 PetscFunctionReturn(PETSC_SUCCESS); 8698 } 8699 8700 /*@ 8701 MatRestrict - $y = A*x$ or $A^T*x$ 8702 8703 Neighbor-wise Collective 8704 8705 Input Parameters: 8706 + A - the matrix 8707 - x - the vector to be restricted 8708 8709 Output Parameter: 8710 . y - the resulting vector 8711 8712 Level: intermediate 8713 8714 Note: 8715 This allows one to use either the restriction or interpolation (its transpose) 8716 matrix to do the restriction 8717 8718 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8719 @*/ 8720 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8721 { 8722 PetscInt M, N, Nx; 8723 8724 PetscFunctionBegin; 8725 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8726 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8727 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8728 PetscCall(MatGetSize(A, &M, &N)); 8729 PetscCall(VecGetSize(x, &Nx)); 8730 if (M == Nx) { 8731 PetscCall(MatMultTranspose(A, x, y)); 8732 } else { 8733 PetscCall(MatMult(A, x, y)); 8734 } 8735 PetscFunctionReturn(PETSC_SUCCESS); 8736 } 8737 8738 /*@ 8739 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8740 8741 Neighbor-wise Collective 8742 8743 Input Parameters: 8744 + A - the matrix 8745 . x - the input dense matrix to be multiplied 8746 - w - the input dense matrix to be added to the result 8747 8748 Output Parameter: 8749 . y - the output dense matrix 8750 8751 Level: intermediate 8752 8753 Note: 8754 This allows one to use either the restriction or interpolation (its transpose) 8755 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8756 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8757 8758 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8759 @*/ 8760 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8761 { 8762 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8763 PetscBool trans = PETSC_TRUE; 8764 MatReuse reuse = MAT_INITIAL_MATRIX; 8765 8766 PetscFunctionBegin; 8767 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8768 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8769 PetscValidType(x, 2); 8770 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8771 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8772 PetscCall(MatGetSize(A, &M, &N)); 8773 PetscCall(MatGetSize(x, &Mx, &Nx)); 8774 if (N == Mx) trans = PETSC_FALSE; 8775 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); 8776 Mo = trans ? N : M; 8777 if (*y) { 8778 PetscCall(MatGetSize(*y, &My, &Ny)); 8779 if (Mo == My && Nx == Ny) { 8780 reuse = MAT_REUSE_MATRIX; 8781 } else { 8782 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); 8783 PetscCall(MatDestroy(y)); 8784 } 8785 } 8786 8787 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8788 PetscBool flg; 8789 8790 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8791 if (w) { 8792 PetscInt My, Ny, Mw, Nw; 8793 8794 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8795 PetscCall(MatGetSize(*y, &My, &Ny)); 8796 PetscCall(MatGetSize(w, &Mw, &Nw)); 8797 if (!flg || My != Mw || Ny != Nw) w = NULL; 8798 } 8799 if (!w) { 8800 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8801 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8802 PetscCall(PetscObjectDereference((PetscObject)w)); 8803 } else { 8804 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8805 } 8806 } 8807 if (!trans) { 8808 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8809 } else { 8810 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8811 } 8812 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8813 PetscFunctionReturn(PETSC_SUCCESS); 8814 } 8815 8816 /*@ 8817 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8818 8819 Neighbor-wise Collective 8820 8821 Input Parameters: 8822 + A - the matrix 8823 - x - the input dense matrix 8824 8825 Output Parameter: 8826 . y - the output dense matrix 8827 8828 Level: intermediate 8829 8830 Note: 8831 This allows one to use either the restriction or interpolation (its transpose) 8832 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8833 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8834 8835 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8836 @*/ 8837 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8838 { 8839 PetscFunctionBegin; 8840 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8841 PetscFunctionReturn(PETSC_SUCCESS); 8842 } 8843 8844 /*@ 8845 MatMatRestrict - $Y = A*X$ or $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 8852 8853 Output Parameter: 8854 . y - the output dense matrix 8855 8856 Level: intermediate 8857 8858 Note: 8859 This allows one to use either the restriction or interpolation (its transpose) 8860 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8861 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8862 8863 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8864 @*/ 8865 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8866 { 8867 PetscFunctionBegin; 8868 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8869 PetscFunctionReturn(PETSC_SUCCESS); 8870 } 8871 8872 /*@ 8873 MatGetNullSpace - retrieves the null space of a matrix. 8874 8875 Logically Collective 8876 8877 Input Parameters: 8878 + mat - the matrix 8879 - nullsp - the null space object 8880 8881 Level: developer 8882 8883 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8884 @*/ 8885 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8886 { 8887 PetscFunctionBegin; 8888 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8889 PetscAssertPointer(nullsp, 2); 8890 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8891 PetscFunctionReturn(PETSC_SUCCESS); 8892 } 8893 8894 /*@C 8895 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8896 8897 Logically Collective 8898 8899 Input Parameters: 8900 + n - the number of matrices 8901 - mat - the array of matrices 8902 8903 Output Parameters: 8904 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space 8905 8906 Level: developer 8907 8908 Note: 8909 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8910 8911 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8912 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8913 @*/ 8914 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8915 { 8916 PetscFunctionBegin; 8917 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8918 PetscAssertPointer(mat, 2); 8919 PetscAssertPointer(nullsp, 3); 8920 8921 PetscCall(PetscCalloc1(3 * n, nullsp)); 8922 for (PetscInt i = 0; i < n; i++) { 8923 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8924 (*nullsp)[i] = mat[i]->nullsp; 8925 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8926 (*nullsp)[n + i] = mat[i]->nearnullsp; 8927 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8928 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8929 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8930 } 8931 PetscFunctionReturn(PETSC_SUCCESS); 8932 } 8933 8934 /*@C 8935 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8936 8937 Logically Collective 8938 8939 Input Parameters: 8940 + n - the number of matrices 8941 . mat - the array of matrices 8942 - nullsp - an array of null spaces, `NULL` if the null space does not exist 8943 8944 Level: developer 8945 8946 Note: 8947 Call `MatGetNullSpaces()` to create `nullsp` 8948 8949 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8950 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8951 @*/ 8952 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8953 { 8954 PetscFunctionBegin; 8955 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8956 PetscAssertPointer(mat, 2); 8957 PetscAssertPointer(nullsp, 3); 8958 PetscAssertPointer(*nullsp, 3); 8959 8960 for (PetscInt i = 0; i < n; i++) { 8961 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8962 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8963 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8964 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8965 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8966 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8967 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8968 } 8969 PetscCall(PetscFree(*nullsp)); 8970 PetscFunctionReturn(PETSC_SUCCESS); 8971 } 8972 8973 /*@ 8974 MatSetNullSpace - attaches a null space to a matrix. 8975 8976 Logically Collective 8977 8978 Input Parameters: 8979 + mat - the matrix 8980 - nullsp - the null space object 8981 8982 Level: advanced 8983 8984 Notes: 8985 This null space is used by the `KSP` linear solvers to solve singular systems. 8986 8987 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` 8988 8989 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 8990 to zero but the linear system will still be solved in a least squares sense. 8991 8992 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8993 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)$. 8994 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 8995 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 8996 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$). 8997 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8998 8999 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9000 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9001 routine also automatically calls `MatSetTransposeNullSpace()`. 9002 9003 The user should call `MatNullSpaceDestroy()`. 9004 9005 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9006 `KSPSetPCSide()` 9007 @*/ 9008 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9009 { 9010 PetscFunctionBegin; 9011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9012 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9013 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9014 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9015 mat->nullsp = nullsp; 9016 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9017 PetscFunctionReturn(PETSC_SUCCESS); 9018 } 9019 9020 /*@ 9021 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9022 9023 Logically Collective 9024 9025 Input Parameters: 9026 + mat - the matrix 9027 - nullsp - the null space object 9028 9029 Level: developer 9030 9031 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9032 @*/ 9033 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9034 { 9035 PetscFunctionBegin; 9036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9037 PetscValidType(mat, 1); 9038 PetscAssertPointer(nullsp, 2); 9039 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9040 PetscFunctionReturn(PETSC_SUCCESS); 9041 } 9042 9043 /*@ 9044 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9045 9046 Logically Collective 9047 9048 Input Parameters: 9049 + mat - the matrix 9050 - nullsp - the null space object 9051 9052 Level: advanced 9053 9054 Notes: 9055 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9056 9057 See `MatSetNullSpace()` 9058 9059 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9060 @*/ 9061 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9062 { 9063 PetscFunctionBegin; 9064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9065 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9066 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9067 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9068 mat->transnullsp = nullsp; 9069 PetscFunctionReturn(PETSC_SUCCESS); 9070 } 9071 9072 /*@ 9073 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9074 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9075 9076 Logically Collective 9077 9078 Input Parameters: 9079 + mat - the matrix 9080 - nullsp - the null space object 9081 9082 Level: advanced 9083 9084 Notes: 9085 Overwrites any previous near null space that may have been attached 9086 9087 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9088 9089 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9090 @*/ 9091 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9092 { 9093 PetscFunctionBegin; 9094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9095 PetscValidType(mat, 1); 9096 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9097 MatCheckPreallocated(mat, 1); 9098 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9099 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9100 mat->nearnullsp = nullsp; 9101 PetscFunctionReturn(PETSC_SUCCESS); 9102 } 9103 9104 /*@ 9105 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9106 9107 Not Collective 9108 9109 Input Parameter: 9110 . mat - the matrix 9111 9112 Output Parameter: 9113 . nullsp - the null space object, `NULL` if not set 9114 9115 Level: advanced 9116 9117 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9118 @*/ 9119 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9120 { 9121 PetscFunctionBegin; 9122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9123 PetscValidType(mat, 1); 9124 PetscAssertPointer(nullsp, 2); 9125 MatCheckPreallocated(mat, 1); 9126 *nullsp = mat->nearnullsp; 9127 PetscFunctionReturn(PETSC_SUCCESS); 9128 } 9129 9130 /*@C 9131 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9132 9133 Collective 9134 9135 Input Parameters: 9136 + mat - the matrix 9137 . row - row/column permutation 9138 - info - information on desired factorization process 9139 9140 Level: developer 9141 9142 Notes: 9143 Probably really in-place only when level of fill is zero, otherwise allocates 9144 new space to store factored matrix and deletes previous memory. 9145 9146 Most users should employ the `KSP` interface for linear solvers 9147 instead of working directly with matrix algebra routines such as this. 9148 See, e.g., `KSPCreate()`. 9149 9150 Developer Note: 9151 The Fortran interface is not autogenerated as the 9152 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9153 9154 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9155 @*/ 9156 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9157 { 9158 PetscFunctionBegin; 9159 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9160 PetscValidType(mat, 1); 9161 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9162 PetscAssertPointer(info, 3); 9163 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9164 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9165 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9166 MatCheckPreallocated(mat, 1); 9167 PetscUseTypeMethod(mat, iccfactor, row, info); 9168 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9169 PetscFunctionReturn(PETSC_SUCCESS); 9170 } 9171 9172 /*@ 9173 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9174 ghosted ones. 9175 9176 Not Collective 9177 9178 Input Parameters: 9179 + mat - the matrix 9180 - diag - the diagonal values, including ghost ones 9181 9182 Level: developer 9183 9184 Notes: 9185 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9186 9187 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9188 9189 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9190 @*/ 9191 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9192 { 9193 PetscMPIInt size; 9194 9195 PetscFunctionBegin; 9196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9197 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9198 PetscValidType(mat, 1); 9199 9200 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9201 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9202 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9203 if (size == 1) { 9204 PetscInt n, m; 9205 PetscCall(VecGetSize(diag, &n)); 9206 PetscCall(MatGetSize(mat, NULL, &m)); 9207 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9208 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9209 } else { 9210 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9211 } 9212 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9214 PetscFunctionReturn(PETSC_SUCCESS); 9215 } 9216 9217 /*@ 9218 MatGetInertia - Gets the inertia from a factored matrix 9219 9220 Collective 9221 9222 Input Parameter: 9223 . mat - the matrix 9224 9225 Output Parameters: 9226 + nneg - number of negative eigenvalues 9227 . nzero - number of zero eigenvalues 9228 - npos - number of positive eigenvalues 9229 9230 Level: advanced 9231 9232 Note: 9233 Matrix must have been factored by `MatCholeskyFactor()` 9234 9235 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9236 @*/ 9237 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9238 { 9239 PetscFunctionBegin; 9240 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9241 PetscValidType(mat, 1); 9242 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9244 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9245 PetscFunctionReturn(PETSC_SUCCESS); 9246 } 9247 9248 /*@C 9249 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9250 9251 Neighbor-wise Collective 9252 9253 Input Parameters: 9254 + mat - the factored matrix obtained with `MatGetFactor()` 9255 - b - the right-hand-side vectors 9256 9257 Output Parameter: 9258 . x - the result vectors 9259 9260 Level: developer 9261 9262 Note: 9263 The vectors `b` and `x` cannot be the same. I.e., one cannot 9264 call `MatSolves`(A,x,x). 9265 9266 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9267 @*/ 9268 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9269 { 9270 PetscFunctionBegin; 9271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9272 PetscValidType(mat, 1); 9273 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9274 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9275 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9276 9277 MatCheckPreallocated(mat, 1); 9278 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9279 PetscUseTypeMethod(mat, solves, b, x); 9280 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9281 PetscFunctionReturn(PETSC_SUCCESS); 9282 } 9283 9284 /*@ 9285 MatIsSymmetric - Test whether a matrix is symmetric 9286 9287 Collective 9288 9289 Input Parameters: 9290 + A - the matrix to test 9291 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9292 9293 Output Parameter: 9294 . flg - the result 9295 9296 Level: intermediate 9297 9298 Notes: 9299 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9300 9301 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9302 9303 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9304 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9305 9306 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9307 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9308 @*/ 9309 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9310 { 9311 PetscFunctionBegin; 9312 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9313 PetscAssertPointer(flg, 3); 9314 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9315 else { 9316 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9317 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9318 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9319 } 9320 PetscFunctionReturn(PETSC_SUCCESS); 9321 } 9322 9323 /*@ 9324 MatIsHermitian - Test whether a matrix is Hermitian 9325 9326 Collective 9327 9328 Input Parameters: 9329 + A - the matrix to test 9330 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9331 9332 Output Parameter: 9333 . flg - the result 9334 9335 Level: intermediate 9336 9337 Notes: 9338 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9339 9340 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9341 9342 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9343 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9344 9345 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9346 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9347 @*/ 9348 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9349 { 9350 PetscFunctionBegin; 9351 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9352 PetscAssertPointer(flg, 3); 9353 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9354 else { 9355 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9356 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9357 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9358 } 9359 PetscFunctionReturn(PETSC_SUCCESS); 9360 } 9361 9362 /*@ 9363 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9364 9365 Not Collective 9366 9367 Input Parameter: 9368 . A - the matrix to check 9369 9370 Output Parameters: 9371 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9372 - flg - the result (only valid if set is `PETSC_TRUE`) 9373 9374 Level: advanced 9375 9376 Notes: 9377 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9378 if you want it explicitly checked 9379 9380 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9381 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9382 9383 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9384 @*/ 9385 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9386 { 9387 PetscFunctionBegin; 9388 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9389 PetscAssertPointer(set, 2); 9390 PetscAssertPointer(flg, 3); 9391 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9392 *set = PETSC_TRUE; 9393 *flg = PetscBool3ToBool(A->symmetric); 9394 } else { 9395 *set = PETSC_FALSE; 9396 } 9397 PetscFunctionReturn(PETSC_SUCCESS); 9398 } 9399 9400 /*@ 9401 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9402 9403 Not Collective 9404 9405 Input Parameter: 9406 . A - the matrix to check 9407 9408 Output Parameters: 9409 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9410 - flg - the result (only valid if set is `PETSC_TRUE`) 9411 9412 Level: advanced 9413 9414 Notes: 9415 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9416 9417 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9418 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9419 9420 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9421 @*/ 9422 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9423 { 9424 PetscFunctionBegin; 9425 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9426 PetscAssertPointer(set, 2); 9427 PetscAssertPointer(flg, 3); 9428 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9429 *set = PETSC_TRUE; 9430 *flg = PetscBool3ToBool(A->spd); 9431 } else { 9432 *set = PETSC_FALSE; 9433 } 9434 PetscFunctionReturn(PETSC_SUCCESS); 9435 } 9436 9437 /*@ 9438 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9439 9440 Not Collective 9441 9442 Input Parameter: 9443 . A - the matrix to check 9444 9445 Output Parameters: 9446 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9447 - flg - the result (only valid if set is `PETSC_TRUE`) 9448 9449 Level: advanced 9450 9451 Notes: 9452 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9453 if you want it explicitly checked 9454 9455 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9456 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9457 9458 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9459 @*/ 9460 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9461 { 9462 PetscFunctionBegin; 9463 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9464 PetscAssertPointer(set, 2); 9465 PetscAssertPointer(flg, 3); 9466 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9467 *set = PETSC_TRUE; 9468 *flg = PetscBool3ToBool(A->hermitian); 9469 } else { 9470 *set = PETSC_FALSE; 9471 } 9472 PetscFunctionReturn(PETSC_SUCCESS); 9473 } 9474 9475 /*@ 9476 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9477 9478 Collective 9479 9480 Input Parameter: 9481 . A - the matrix to test 9482 9483 Output Parameter: 9484 . flg - the result 9485 9486 Level: intermediate 9487 9488 Notes: 9489 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9490 9491 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 9492 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9493 9494 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9495 @*/ 9496 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9497 { 9498 PetscFunctionBegin; 9499 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9500 PetscAssertPointer(flg, 2); 9501 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9502 *flg = PetscBool3ToBool(A->structurally_symmetric); 9503 } else { 9504 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9505 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9506 } 9507 PetscFunctionReturn(PETSC_SUCCESS); 9508 } 9509 9510 /*@ 9511 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9512 9513 Not Collective 9514 9515 Input Parameter: 9516 . A - the matrix to check 9517 9518 Output Parameters: 9519 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9520 - flg - the result (only valid if set is PETSC_TRUE) 9521 9522 Level: advanced 9523 9524 Notes: 9525 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 9526 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9527 9528 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9529 9530 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9531 @*/ 9532 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9533 { 9534 PetscFunctionBegin; 9535 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9536 PetscAssertPointer(set, 2); 9537 PetscAssertPointer(flg, 3); 9538 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9539 *set = PETSC_TRUE; 9540 *flg = PetscBool3ToBool(A->structurally_symmetric); 9541 } else { 9542 *set = PETSC_FALSE; 9543 } 9544 PetscFunctionReturn(PETSC_SUCCESS); 9545 } 9546 9547 /*@ 9548 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9549 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9550 9551 Not Collective 9552 9553 Input Parameter: 9554 . mat - the matrix 9555 9556 Output Parameters: 9557 + nstash - the size of the stash 9558 . reallocs - the number of additional mallocs incurred. 9559 . bnstash - the size of the block stash 9560 - breallocs - the number of additional mallocs incurred.in the block stash 9561 9562 Level: advanced 9563 9564 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9565 @*/ 9566 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9567 { 9568 PetscFunctionBegin; 9569 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9570 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9571 PetscFunctionReturn(PETSC_SUCCESS); 9572 } 9573 9574 /*@C 9575 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9576 parallel layout, `PetscLayout` for rows and columns 9577 9578 Collective 9579 9580 Input Parameter: 9581 . mat - the matrix 9582 9583 Output Parameters: 9584 + right - (optional) vector that the matrix can be multiplied against 9585 - left - (optional) vector that the matrix vector product can be stored in 9586 9587 Level: advanced 9588 9589 Notes: 9590 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()`. 9591 9592 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9593 9594 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9595 @*/ 9596 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9597 { 9598 PetscFunctionBegin; 9599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9600 PetscValidType(mat, 1); 9601 if (mat->ops->getvecs) { 9602 PetscUseTypeMethod(mat, getvecs, right, left); 9603 } else { 9604 if (right) { 9605 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9606 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9607 PetscCall(VecSetType(*right, mat->defaultvectype)); 9608 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9609 if (mat->boundtocpu && mat->bindingpropagates) { 9610 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9611 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9612 } 9613 #endif 9614 } 9615 if (left) { 9616 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9617 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9618 PetscCall(VecSetType(*left, mat->defaultvectype)); 9619 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9620 if (mat->boundtocpu && mat->bindingpropagates) { 9621 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9622 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9623 } 9624 #endif 9625 } 9626 } 9627 PetscFunctionReturn(PETSC_SUCCESS); 9628 } 9629 9630 /*@C 9631 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9632 with default values. 9633 9634 Not Collective 9635 9636 Input Parameter: 9637 . info - the `MatFactorInfo` data structure 9638 9639 Level: developer 9640 9641 Notes: 9642 The solvers are generally used through the `KSP` and `PC` objects, for example 9643 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9644 9645 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9646 9647 Developer Note: 9648 The Fortran interface is not autogenerated as the 9649 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9650 9651 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9652 @*/ 9653 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9654 { 9655 PetscFunctionBegin; 9656 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9657 PetscFunctionReturn(PETSC_SUCCESS); 9658 } 9659 9660 /*@ 9661 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9662 9663 Collective 9664 9665 Input Parameters: 9666 + mat - the factored matrix 9667 - is - the index set defining the Schur indices (0-based) 9668 9669 Level: advanced 9670 9671 Notes: 9672 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9673 9674 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9675 9676 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9677 9678 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9679 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9680 @*/ 9681 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9682 { 9683 PetscErrorCode (*f)(Mat, IS); 9684 9685 PetscFunctionBegin; 9686 PetscValidType(mat, 1); 9687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9688 PetscValidType(is, 2); 9689 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9690 PetscCheckSameComm(mat, 1, is, 2); 9691 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9692 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9693 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9694 PetscCall(MatDestroy(&mat->schur)); 9695 PetscCall((*f)(mat, is)); 9696 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9697 PetscFunctionReturn(PETSC_SUCCESS); 9698 } 9699 9700 /*@ 9701 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9702 9703 Logically Collective 9704 9705 Input Parameters: 9706 + F - the factored matrix obtained by calling `MatGetFactor()` 9707 . S - location where to return the Schur complement, can be `NULL` 9708 - status - the status of the Schur complement matrix, can be `NULL` 9709 9710 Level: advanced 9711 9712 Notes: 9713 You must call `MatFactorSetSchurIS()` before calling this routine. 9714 9715 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9716 9717 The routine provides a copy of the Schur matrix stored within the solver data structures. 9718 The caller must destroy the object when it is no longer needed. 9719 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9720 9721 Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does) 9722 9723 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9724 9725 Developer Note: 9726 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9727 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9728 9729 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9730 @*/ 9731 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9732 { 9733 PetscFunctionBegin; 9734 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9735 if (S) PetscAssertPointer(S, 2); 9736 if (status) PetscAssertPointer(status, 3); 9737 if (S) { 9738 PetscErrorCode (*f)(Mat, Mat *); 9739 9740 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9741 if (f) { 9742 PetscCall((*f)(F, S)); 9743 } else { 9744 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9745 } 9746 } 9747 if (status) *status = F->schur_status; 9748 PetscFunctionReturn(PETSC_SUCCESS); 9749 } 9750 9751 /*@ 9752 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9753 9754 Logically Collective 9755 9756 Input Parameters: 9757 + F - the factored matrix obtained by calling `MatGetFactor()` 9758 . S - location where to return the Schur complement, can be `NULL` 9759 - status - the status of the Schur complement matrix, can be `NULL` 9760 9761 Level: advanced 9762 9763 Notes: 9764 You must call `MatFactorSetSchurIS()` before calling this routine. 9765 9766 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9767 9768 The routine returns a the Schur Complement stored within the data structures of the solver. 9769 9770 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9771 9772 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9773 9774 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9775 9776 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9777 9778 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9779 @*/ 9780 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9781 { 9782 PetscFunctionBegin; 9783 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9784 if (S) { 9785 PetscAssertPointer(S, 2); 9786 *S = F->schur; 9787 } 9788 if (status) { 9789 PetscAssertPointer(status, 3); 9790 *status = F->schur_status; 9791 } 9792 PetscFunctionReturn(PETSC_SUCCESS); 9793 } 9794 9795 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9796 { 9797 Mat S = F->schur; 9798 9799 PetscFunctionBegin; 9800 switch (F->schur_status) { 9801 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9802 case MAT_FACTOR_SCHUR_INVERTED: 9803 if (S) { 9804 S->ops->solve = NULL; 9805 S->ops->matsolve = NULL; 9806 S->ops->solvetranspose = NULL; 9807 S->ops->matsolvetranspose = NULL; 9808 S->ops->solveadd = NULL; 9809 S->ops->solvetransposeadd = NULL; 9810 S->factortype = MAT_FACTOR_NONE; 9811 PetscCall(PetscFree(S->solvertype)); 9812 } 9813 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9814 break; 9815 default: 9816 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9817 } 9818 PetscFunctionReturn(PETSC_SUCCESS); 9819 } 9820 9821 /*@ 9822 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9823 9824 Logically Collective 9825 9826 Input Parameters: 9827 + F - the factored matrix obtained by calling `MatGetFactor()` 9828 . S - location where the Schur complement is stored 9829 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9830 9831 Level: advanced 9832 9833 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9834 @*/ 9835 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9836 { 9837 PetscFunctionBegin; 9838 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9839 if (S) { 9840 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9841 *S = NULL; 9842 } 9843 F->schur_status = status; 9844 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9845 PetscFunctionReturn(PETSC_SUCCESS); 9846 } 9847 9848 /*@ 9849 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9850 9851 Logically Collective 9852 9853 Input Parameters: 9854 + F - the factored matrix obtained by calling `MatGetFactor()` 9855 . rhs - location where the right-hand side of the Schur complement system is stored 9856 - sol - location where the solution of the Schur complement system has to be returned 9857 9858 Level: advanced 9859 9860 Notes: 9861 The sizes of the vectors should match the size of the Schur complement 9862 9863 Must be called after `MatFactorSetSchurIS()` 9864 9865 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9866 @*/ 9867 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9868 { 9869 PetscFunctionBegin; 9870 PetscValidType(F, 1); 9871 PetscValidType(rhs, 2); 9872 PetscValidType(sol, 3); 9873 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9874 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9875 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9876 PetscCheckSameComm(F, 1, rhs, 2); 9877 PetscCheckSameComm(F, 1, sol, 3); 9878 PetscCall(MatFactorFactorizeSchurComplement(F)); 9879 switch (F->schur_status) { 9880 case MAT_FACTOR_SCHUR_FACTORED: 9881 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9882 break; 9883 case MAT_FACTOR_SCHUR_INVERTED: 9884 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9885 break; 9886 default: 9887 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9888 } 9889 PetscFunctionReturn(PETSC_SUCCESS); 9890 } 9891 9892 /*@ 9893 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9894 9895 Logically Collective 9896 9897 Input Parameters: 9898 + F - the factored matrix obtained by calling `MatGetFactor()` 9899 . rhs - location where the right-hand side of the Schur complement system is stored 9900 - sol - location where the solution of the Schur complement system has to be returned 9901 9902 Level: advanced 9903 9904 Notes: 9905 The sizes of the vectors should match the size of the Schur complement 9906 9907 Must be called after `MatFactorSetSchurIS()` 9908 9909 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9910 @*/ 9911 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9912 { 9913 PetscFunctionBegin; 9914 PetscValidType(F, 1); 9915 PetscValidType(rhs, 2); 9916 PetscValidType(sol, 3); 9917 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9918 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9919 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9920 PetscCheckSameComm(F, 1, rhs, 2); 9921 PetscCheckSameComm(F, 1, sol, 3); 9922 PetscCall(MatFactorFactorizeSchurComplement(F)); 9923 switch (F->schur_status) { 9924 case MAT_FACTOR_SCHUR_FACTORED: 9925 PetscCall(MatSolve(F->schur, rhs, sol)); 9926 break; 9927 case MAT_FACTOR_SCHUR_INVERTED: 9928 PetscCall(MatMult(F->schur, rhs, sol)); 9929 break; 9930 default: 9931 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9932 } 9933 PetscFunctionReturn(PETSC_SUCCESS); 9934 } 9935 9936 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9937 #if PetscDefined(HAVE_CUDA) 9938 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9939 #endif 9940 9941 /* Schur status updated in the interface */ 9942 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9943 { 9944 Mat S = F->schur; 9945 9946 PetscFunctionBegin; 9947 if (S) { 9948 PetscMPIInt size; 9949 PetscBool isdense, isdensecuda; 9950 9951 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9952 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9953 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9954 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9955 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9956 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9957 if (isdense) { 9958 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9959 } else if (isdensecuda) { 9960 #if defined(PETSC_HAVE_CUDA) 9961 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9962 #endif 9963 } 9964 // HIP?????????????? 9965 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9966 } 9967 PetscFunctionReturn(PETSC_SUCCESS); 9968 } 9969 9970 /*@ 9971 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9972 9973 Logically Collective 9974 9975 Input Parameter: 9976 . F - the factored matrix obtained by calling `MatGetFactor()` 9977 9978 Level: advanced 9979 9980 Notes: 9981 Must be called after `MatFactorSetSchurIS()`. 9982 9983 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9984 9985 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9986 @*/ 9987 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9988 { 9989 PetscFunctionBegin; 9990 PetscValidType(F, 1); 9991 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9992 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9993 PetscCall(MatFactorFactorizeSchurComplement(F)); 9994 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9995 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9996 PetscFunctionReturn(PETSC_SUCCESS); 9997 } 9998 9999 /*@ 10000 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10001 10002 Logically Collective 10003 10004 Input Parameter: 10005 . F - the factored matrix obtained by calling `MatGetFactor()` 10006 10007 Level: advanced 10008 10009 Note: 10010 Must be called after `MatFactorSetSchurIS()` 10011 10012 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10013 @*/ 10014 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10015 { 10016 MatFactorInfo info; 10017 10018 PetscFunctionBegin; 10019 PetscValidType(F, 1); 10020 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10021 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10022 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10023 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10024 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10025 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10026 } else { 10027 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10028 } 10029 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10030 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10031 PetscFunctionReturn(PETSC_SUCCESS); 10032 } 10033 10034 /*@ 10035 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10036 10037 Neighbor-wise Collective 10038 10039 Input Parameters: 10040 + A - the matrix 10041 . P - the projection matrix 10042 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10043 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10044 if the result is a dense matrix this is irrelevant 10045 10046 Output Parameter: 10047 . C - the product matrix 10048 10049 Level: intermediate 10050 10051 Notes: 10052 C will be created and must be destroyed by the user with `MatDestroy()`. 10053 10054 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10055 10056 Developer Note: 10057 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10058 10059 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10060 @*/ 10061 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10062 { 10063 PetscFunctionBegin; 10064 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10065 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10066 10067 if (scall == MAT_INITIAL_MATRIX) { 10068 PetscCall(MatProductCreate(A, P, NULL, C)); 10069 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10070 PetscCall(MatProductSetAlgorithm(*C, "default")); 10071 PetscCall(MatProductSetFill(*C, fill)); 10072 10073 (*C)->product->api_user = PETSC_TRUE; 10074 PetscCall(MatProductSetFromOptions(*C)); 10075 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); 10076 PetscCall(MatProductSymbolic(*C)); 10077 } else { /* scall == MAT_REUSE_MATRIX */ 10078 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10079 } 10080 10081 PetscCall(MatProductNumeric(*C)); 10082 (*C)->symmetric = A->symmetric; 10083 (*C)->spd = A->spd; 10084 PetscFunctionReturn(PETSC_SUCCESS); 10085 } 10086 10087 /*@ 10088 MatRARt - Creates the matrix product $C = R * A * R^T$ 10089 10090 Neighbor-wise Collective 10091 10092 Input Parameters: 10093 + A - the matrix 10094 . R - the projection matrix 10095 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10096 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10097 if the result is a dense matrix this is irrelevant 10098 10099 Output Parameter: 10100 . C - the product matrix 10101 10102 Level: intermediate 10103 10104 Notes: 10105 C will be created and must be destroyed by the user with `MatDestroy()`. 10106 10107 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10108 10109 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10110 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10111 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10112 We recommend using MatPtAP(). 10113 10114 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10115 @*/ 10116 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10117 { 10118 PetscFunctionBegin; 10119 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10120 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10121 10122 if (scall == MAT_INITIAL_MATRIX) { 10123 PetscCall(MatProductCreate(A, R, NULL, C)); 10124 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10125 PetscCall(MatProductSetAlgorithm(*C, "default")); 10126 PetscCall(MatProductSetFill(*C, fill)); 10127 10128 (*C)->product->api_user = PETSC_TRUE; 10129 PetscCall(MatProductSetFromOptions(*C)); 10130 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); 10131 PetscCall(MatProductSymbolic(*C)); 10132 } else { /* scall == MAT_REUSE_MATRIX */ 10133 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10134 } 10135 10136 PetscCall(MatProductNumeric(*C)); 10137 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10138 PetscFunctionReturn(PETSC_SUCCESS); 10139 } 10140 10141 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10142 { 10143 PetscBool flg = PETSC_TRUE; 10144 10145 PetscFunctionBegin; 10146 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10147 if (scall == MAT_INITIAL_MATRIX) { 10148 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10149 PetscCall(MatProductCreate(A, B, NULL, C)); 10150 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10151 PetscCall(MatProductSetFill(*C, fill)); 10152 } else { /* scall == MAT_REUSE_MATRIX */ 10153 Mat_Product *product = (*C)->product; 10154 10155 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10156 if (flg && product && product->type != ptype) { 10157 PetscCall(MatProductClear(*C)); 10158 product = NULL; 10159 } 10160 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10161 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10162 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10163 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10164 product = (*C)->product; 10165 product->fill = fill; 10166 product->clear = PETSC_TRUE; 10167 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10168 flg = PETSC_FALSE; 10169 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10170 } 10171 } 10172 if (flg) { 10173 (*C)->product->api_user = PETSC_TRUE; 10174 PetscCall(MatProductSetType(*C, ptype)); 10175 PetscCall(MatProductSetFromOptions(*C)); 10176 PetscCall(MatProductSymbolic(*C)); 10177 } 10178 PetscCall(MatProductNumeric(*C)); 10179 PetscFunctionReturn(PETSC_SUCCESS); 10180 } 10181 10182 /*@ 10183 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10184 10185 Neighbor-wise Collective 10186 10187 Input Parameters: 10188 + A - the left matrix 10189 . B - the right matrix 10190 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10191 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10192 if the result is a dense matrix this is irrelevant 10193 10194 Output Parameter: 10195 . C - the product matrix 10196 10197 Notes: 10198 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10199 10200 `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 10201 call to this function with `MAT_INITIAL_MATRIX`. 10202 10203 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10204 10205 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`, 10206 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10207 10208 Example of Usage: 10209 .vb 10210 MatProductCreate(A,B,NULL,&C); 10211 MatProductSetType(C,MATPRODUCT_AB); 10212 MatProductSymbolic(C); 10213 MatProductNumeric(C); // compute C=A * B 10214 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10215 MatProductNumeric(C); 10216 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10217 MatProductNumeric(C); 10218 .ve 10219 10220 Level: intermediate 10221 10222 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10223 @*/ 10224 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10225 { 10226 PetscFunctionBegin; 10227 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10228 PetscFunctionReturn(PETSC_SUCCESS); 10229 } 10230 10231 /*@ 10232 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10233 10234 Neighbor-wise Collective 10235 10236 Input Parameters: 10237 + A - the left matrix 10238 . B - the right matrix 10239 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10240 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10241 10242 Output Parameter: 10243 . C - the product matrix 10244 10245 Options Database Key: 10246 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10247 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10248 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10249 10250 Level: intermediate 10251 10252 Notes: 10253 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10254 10255 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10256 10257 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10258 actually needed. 10259 10260 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10261 and for pairs of `MATMPIDENSE` matrices. 10262 10263 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10264 10265 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10266 @*/ 10267 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10268 { 10269 PetscFunctionBegin; 10270 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10271 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10272 PetscFunctionReturn(PETSC_SUCCESS); 10273 } 10274 10275 /*@ 10276 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10277 10278 Neighbor-wise Collective 10279 10280 Input Parameters: 10281 + A - the left matrix 10282 . B - the right matrix 10283 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10284 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10285 10286 Output Parameter: 10287 . C - the product matrix 10288 10289 Level: intermediate 10290 10291 Notes: 10292 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10293 10294 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10295 10296 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10297 10298 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10299 actually needed. 10300 10301 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10302 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10303 10304 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10305 @*/ 10306 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10307 { 10308 PetscFunctionBegin; 10309 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10310 PetscFunctionReturn(PETSC_SUCCESS); 10311 } 10312 10313 /*@ 10314 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10315 10316 Neighbor-wise Collective 10317 10318 Input Parameters: 10319 + A - the left matrix 10320 . B - the middle matrix 10321 . C - the right matrix 10322 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10323 - 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 10324 if the result is a dense matrix this is irrelevant 10325 10326 Output Parameter: 10327 . D - the product matrix 10328 10329 Level: intermediate 10330 10331 Notes: 10332 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10333 10334 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10335 10336 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10337 10338 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10339 actually needed. 10340 10341 If you have many matrices with the same non-zero structure to multiply, you 10342 should use `MAT_REUSE_MATRIX` in all calls but the first 10343 10344 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10345 @*/ 10346 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10347 { 10348 PetscFunctionBegin; 10349 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10350 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10351 10352 if (scall == MAT_INITIAL_MATRIX) { 10353 PetscCall(MatProductCreate(A, B, C, D)); 10354 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10355 PetscCall(MatProductSetAlgorithm(*D, "default")); 10356 PetscCall(MatProductSetFill(*D, fill)); 10357 10358 (*D)->product->api_user = PETSC_TRUE; 10359 PetscCall(MatProductSetFromOptions(*D)); 10360 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, 10361 ((PetscObject)C)->type_name); 10362 PetscCall(MatProductSymbolic(*D)); 10363 } else { /* user may change input matrices when REUSE */ 10364 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10365 } 10366 PetscCall(MatProductNumeric(*D)); 10367 PetscFunctionReturn(PETSC_SUCCESS); 10368 } 10369 10370 /*@ 10371 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10372 10373 Collective 10374 10375 Input Parameters: 10376 + mat - the matrix 10377 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10378 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10379 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10380 10381 Output Parameter: 10382 . matredundant - redundant matrix 10383 10384 Level: advanced 10385 10386 Notes: 10387 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10388 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10389 10390 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10391 calling it. 10392 10393 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10394 10395 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10396 @*/ 10397 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10398 { 10399 MPI_Comm comm; 10400 PetscMPIInt size; 10401 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10402 Mat_Redundant *redund = NULL; 10403 PetscSubcomm psubcomm = NULL; 10404 MPI_Comm subcomm_in = subcomm; 10405 Mat *matseq; 10406 IS isrow, iscol; 10407 PetscBool newsubcomm = PETSC_FALSE; 10408 10409 PetscFunctionBegin; 10410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10411 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10412 PetscAssertPointer(*matredundant, 5); 10413 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10414 } 10415 10416 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10417 if (size == 1 || nsubcomm == 1) { 10418 if (reuse == MAT_INITIAL_MATRIX) { 10419 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10420 } else { 10421 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"); 10422 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10423 } 10424 PetscFunctionReturn(PETSC_SUCCESS); 10425 } 10426 10427 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10428 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10429 MatCheckPreallocated(mat, 1); 10430 10431 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10432 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10433 /* create psubcomm, then get subcomm */ 10434 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10435 PetscCallMPI(MPI_Comm_size(comm, &size)); 10436 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10437 10438 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10439 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10440 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10441 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10442 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10443 newsubcomm = PETSC_TRUE; 10444 PetscCall(PetscSubcommDestroy(&psubcomm)); 10445 } 10446 10447 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10448 if (reuse == MAT_INITIAL_MATRIX) { 10449 mloc_sub = PETSC_DECIDE; 10450 nloc_sub = PETSC_DECIDE; 10451 if (bs < 1) { 10452 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10453 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10454 } else { 10455 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10456 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10457 } 10458 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10459 rstart = rend - mloc_sub; 10460 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10461 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10462 PetscCall(ISSetIdentity(iscol)); 10463 } else { /* reuse == MAT_REUSE_MATRIX */ 10464 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"); 10465 /* retrieve subcomm */ 10466 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10467 redund = (*matredundant)->redundant; 10468 isrow = redund->isrow; 10469 iscol = redund->iscol; 10470 matseq = redund->matseq; 10471 } 10472 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10473 10474 /* get matredundant over subcomm */ 10475 if (reuse == MAT_INITIAL_MATRIX) { 10476 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10477 10478 /* create a supporting struct and attach it to C for reuse */ 10479 PetscCall(PetscNew(&redund)); 10480 (*matredundant)->redundant = redund; 10481 redund->isrow = isrow; 10482 redund->iscol = iscol; 10483 redund->matseq = matseq; 10484 if (newsubcomm) { 10485 redund->subcomm = subcomm; 10486 } else { 10487 redund->subcomm = MPI_COMM_NULL; 10488 } 10489 } else { 10490 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10491 } 10492 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10493 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10494 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10495 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10496 } 10497 #endif 10498 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10499 PetscFunctionReturn(PETSC_SUCCESS); 10500 } 10501 10502 /*@C 10503 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10504 a given `Mat`. Each submatrix can span multiple procs. 10505 10506 Collective 10507 10508 Input Parameters: 10509 + mat - the matrix 10510 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10511 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10512 10513 Output Parameter: 10514 . subMat - parallel sub-matrices each spanning a given `subcomm` 10515 10516 Level: advanced 10517 10518 Notes: 10519 The submatrix partition across processors is dictated by `subComm` a 10520 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10521 is not restricted to be grouped with consecutive original MPI processes. 10522 10523 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10524 map directly to the layout of the original matrix [wrt the local 10525 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10526 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10527 the `subMat`. However the offDiagMat looses some columns - and this is 10528 reconstructed with `MatSetValues()` 10529 10530 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10531 10532 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10533 @*/ 10534 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10535 { 10536 PetscMPIInt commsize, subCommSize; 10537 10538 PetscFunctionBegin; 10539 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10540 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10541 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10542 10543 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"); 10544 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10545 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10546 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10547 PetscFunctionReturn(PETSC_SUCCESS); 10548 } 10549 10550 /*@ 10551 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10552 10553 Not Collective 10554 10555 Input Parameters: 10556 + mat - matrix to extract local submatrix from 10557 . isrow - local row indices for submatrix 10558 - iscol - local column indices for submatrix 10559 10560 Output Parameter: 10561 . submat - the submatrix 10562 10563 Level: intermediate 10564 10565 Notes: 10566 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10567 10568 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10569 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10570 10571 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10572 `MatSetValuesBlockedLocal()` will also be implemented. 10573 10574 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10575 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10576 10577 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10578 @*/ 10579 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10580 { 10581 PetscFunctionBegin; 10582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10583 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10584 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10585 PetscCheckSameComm(isrow, 2, iscol, 3); 10586 PetscAssertPointer(submat, 4); 10587 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10588 10589 if (mat->ops->getlocalsubmatrix) { 10590 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10591 } else { 10592 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10593 } 10594 PetscFunctionReturn(PETSC_SUCCESS); 10595 } 10596 10597 /*@ 10598 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10599 10600 Not Collective 10601 10602 Input Parameters: 10603 + mat - matrix to extract local submatrix from 10604 . isrow - local row indices for submatrix 10605 . iscol - local column indices for submatrix 10606 - submat - the submatrix 10607 10608 Level: intermediate 10609 10610 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10611 @*/ 10612 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10613 { 10614 PetscFunctionBegin; 10615 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10616 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10617 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10618 PetscCheckSameComm(isrow, 2, iscol, 3); 10619 PetscAssertPointer(submat, 4); 10620 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10621 10622 if (mat->ops->restorelocalsubmatrix) { 10623 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10624 } else { 10625 PetscCall(MatDestroy(submat)); 10626 } 10627 *submat = NULL; 10628 PetscFunctionReturn(PETSC_SUCCESS); 10629 } 10630 10631 /*@ 10632 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10633 10634 Collective 10635 10636 Input Parameter: 10637 . mat - the matrix 10638 10639 Output Parameter: 10640 . is - if any rows have zero diagonals this contains the list of them 10641 10642 Level: developer 10643 10644 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10645 @*/ 10646 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10647 { 10648 PetscFunctionBegin; 10649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10650 PetscValidType(mat, 1); 10651 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10652 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10653 10654 if (!mat->ops->findzerodiagonals) { 10655 Vec diag; 10656 const PetscScalar *a; 10657 PetscInt *rows; 10658 PetscInt rStart, rEnd, r, nrow = 0; 10659 10660 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10661 PetscCall(MatGetDiagonal(mat, diag)); 10662 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10663 PetscCall(VecGetArrayRead(diag, &a)); 10664 for (r = 0; r < rEnd - rStart; ++r) 10665 if (a[r] == 0.0) ++nrow; 10666 PetscCall(PetscMalloc1(nrow, &rows)); 10667 nrow = 0; 10668 for (r = 0; r < rEnd - rStart; ++r) 10669 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10670 PetscCall(VecRestoreArrayRead(diag, &a)); 10671 PetscCall(VecDestroy(&diag)); 10672 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10673 } else { 10674 PetscUseTypeMethod(mat, findzerodiagonals, is); 10675 } 10676 PetscFunctionReturn(PETSC_SUCCESS); 10677 } 10678 10679 /*@ 10680 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10681 10682 Collective 10683 10684 Input Parameter: 10685 . mat - the matrix 10686 10687 Output Parameter: 10688 . is - contains the list of rows with off block diagonal entries 10689 10690 Level: developer 10691 10692 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10693 @*/ 10694 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10695 { 10696 PetscFunctionBegin; 10697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10698 PetscValidType(mat, 1); 10699 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10700 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10701 10702 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10703 PetscFunctionReturn(PETSC_SUCCESS); 10704 } 10705 10706 /*@C 10707 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10708 10709 Collective; No Fortran Support 10710 10711 Input Parameter: 10712 . mat - the matrix 10713 10714 Output Parameter: 10715 . values - the block inverses in column major order (FORTRAN-like) 10716 10717 Level: advanced 10718 10719 Notes: 10720 The size of the blocks is determined by the block size of the matrix. 10721 10722 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10723 10724 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10725 10726 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10727 @*/ 10728 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10729 { 10730 PetscFunctionBegin; 10731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10732 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10733 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10734 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10735 PetscFunctionReturn(PETSC_SUCCESS); 10736 } 10737 10738 /*@C 10739 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10740 10741 Collective; No Fortran Support 10742 10743 Input Parameters: 10744 + mat - the matrix 10745 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10746 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10747 10748 Output Parameter: 10749 . values - the block inverses in column major order (FORTRAN-like) 10750 10751 Level: advanced 10752 10753 Notes: 10754 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10755 10756 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10757 10758 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10759 @*/ 10760 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10761 { 10762 PetscFunctionBegin; 10763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10764 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10765 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10766 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10767 PetscFunctionReturn(PETSC_SUCCESS); 10768 } 10769 10770 /*@ 10771 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10772 10773 Collective 10774 10775 Input Parameters: 10776 + A - the matrix 10777 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10778 10779 Level: advanced 10780 10781 Note: 10782 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10783 10784 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10785 @*/ 10786 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10787 { 10788 const PetscScalar *vals; 10789 PetscInt *dnnz; 10790 PetscInt m, rstart, rend, bs, i, j; 10791 10792 PetscFunctionBegin; 10793 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10794 PetscCall(MatGetBlockSize(A, &bs)); 10795 PetscCall(MatGetLocalSize(A, &m, NULL)); 10796 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10797 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10798 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10799 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10800 PetscCall(PetscFree(dnnz)); 10801 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10802 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10803 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10804 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10805 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10806 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10807 PetscFunctionReturn(PETSC_SUCCESS); 10808 } 10809 10810 /*@C 10811 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10812 via `MatTransposeColoringCreate()`. 10813 10814 Collective 10815 10816 Input Parameter: 10817 . c - coloring context 10818 10819 Level: intermediate 10820 10821 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10822 @*/ 10823 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10824 { 10825 MatTransposeColoring matcolor = *c; 10826 10827 PetscFunctionBegin; 10828 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10829 if (--((PetscObject)matcolor)->refct > 0) { 10830 matcolor = NULL; 10831 PetscFunctionReturn(PETSC_SUCCESS); 10832 } 10833 10834 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10835 PetscCall(PetscFree(matcolor->rows)); 10836 PetscCall(PetscFree(matcolor->den2sp)); 10837 PetscCall(PetscFree(matcolor->colorforcol)); 10838 PetscCall(PetscFree(matcolor->columns)); 10839 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10840 PetscCall(PetscHeaderDestroy(c)); 10841 PetscFunctionReturn(PETSC_SUCCESS); 10842 } 10843 10844 /*@C 10845 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10846 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10847 `MatTransposeColoring` to sparse `B`. 10848 10849 Collective 10850 10851 Input Parameters: 10852 + coloring - coloring context created with `MatTransposeColoringCreate()` 10853 - B - sparse matrix 10854 10855 Output Parameter: 10856 . Btdense - dense matrix $B^T$ 10857 10858 Level: developer 10859 10860 Note: 10861 These are used internally for some implementations of `MatRARt()` 10862 10863 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10864 @*/ 10865 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10866 { 10867 PetscFunctionBegin; 10868 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10869 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10870 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10871 10872 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10873 PetscFunctionReturn(PETSC_SUCCESS); 10874 } 10875 10876 /*@C 10877 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10878 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10879 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10880 $C_{sp}$ from $C_{den}$. 10881 10882 Collective 10883 10884 Input Parameters: 10885 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10886 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10887 10888 Output Parameter: 10889 . Csp - sparse matrix 10890 10891 Level: developer 10892 10893 Note: 10894 These are used internally for some implementations of `MatRARt()` 10895 10896 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10897 @*/ 10898 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10899 { 10900 PetscFunctionBegin; 10901 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10902 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10903 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10904 10905 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10906 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10907 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10908 PetscFunctionReturn(PETSC_SUCCESS); 10909 } 10910 10911 /*@C 10912 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10913 10914 Collective 10915 10916 Input Parameters: 10917 + mat - the matrix product C 10918 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10919 10920 Output Parameter: 10921 . color - the new coloring context 10922 10923 Level: intermediate 10924 10925 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10926 `MatTransColoringApplyDenToSp()` 10927 @*/ 10928 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10929 { 10930 MatTransposeColoring c; 10931 MPI_Comm comm; 10932 10933 PetscFunctionBegin; 10934 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10935 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10936 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10937 10938 c->ctype = iscoloring->ctype; 10939 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10940 10941 *color = c; 10942 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10943 PetscFunctionReturn(PETSC_SUCCESS); 10944 } 10945 10946 /*@ 10947 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10948 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10949 same, otherwise it will be larger 10950 10951 Not Collective 10952 10953 Input Parameter: 10954 . mat - the matrix 10955 10956 Output Parameter: 10957 . state - the current state 10958 10959 Level: intermediate 10960 10961 Notes: 10962 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10963 different matrices 10964 10965 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10966 10967 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10968 10969 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10970 @*/ 10971 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10972 { 10973 PetscFunctionBegin; 10974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10975 *state = mat->nonzerostate; 10976 PetscFunctionReturn(PETSC_SUCCESS); 10977 } 10978 10979 /*@ 10980 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10981 matrices from each processor 10982 10983 Collective 10984 10985 Input Parameters: 10986 + comm - the communicators the parallel matrix will live on 10987 . seqmat - the input sequential matrices 10988 . n - number of local columns (or `PETSC_DECIDE`) 10989 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10990 10991 Output Parameter: 10992 . mpimat - the parallel matrix generated 10993 10994 Level: developer 10995 10996 Note: 10997 The number of columns of the matrix in EACH processor MUST be the same. 10998 10999 .seealso: [](ch_matrices), `Mat` 11000 @*/ 11001 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11002 { 11003 PetscMPIInt size; 11004 11005 PetscFunctionBegin; 11006 PetscCallMPI(MPI_Comm_size(comm, &size)); 11007 if (size == 1) { 11008 if (reuse == MAT_INITIAL_MATRIX) { 11009 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11010 } else { 11011 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11012 } 11013 PetscFunctionReturn(PETSC_SUCCESS); 11014 } 11015 11016 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"); 11017 11018 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11019 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11020 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11021 PetscFunctionReturn(PETSC_SUCCESS); 11022 } 11023 11024 /*@ 11025 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11026 11027 Collective 11028 11029 Input Parameters: 11030 + A - the matrix to create subdomains from 11031 - N - requested number of subdomains 11032 11033 Output Parameters: 11034 + n - number of subdomains resulting on this MPI process 11035 - iss - `IS` list with indices of subdomains on this MPI process 11036 11037 Level: advanced 11038 11039 Note: 11040 The number of subdomains must be smaller than the communicator size 11041 11042 .seealso: [](ch_matrices), `Mat`, `IS` 11043 @*/ 11044 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11045 { 11046 MPI_Comm comm, subcomm; 11047 PetscMPIInt size, rank, color; 11048 PetscInt rstart, rend, k; 11049 11050 PetscFunctionBegin; 11051 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11052 PetscCallMPI(MPI_Comm_size(comm, &size)); 11053 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11054 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); 11055 *n = 1; 11056 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11057 color = rank / k; 11058 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11059 PetscCall(PetscMalloc1(1, iss)); 11060 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11061 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11062 PetscCallMPI(MPI_Comm_free(&subcomm)); 11063 PetscFunctionReturn(PETSC_SUCCESS); 11064 } 11065 11066 /*@ 11067 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11068 11069 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11070 If they are not the same, uses `MatMatMatMult()`. 11071 11072 Once the coarse grid problem is constructed, correct for interpolation operators 11073 that are not of full rank, which can legitimately happen in the case of non-nested 11074 geometric multigrid. 11075 11076 Input Parameters: 11077 + restrct - restriction operator 11078 . dA - fine grid matrix 11079 . interpolate - interpolation operator 11080 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11081 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11082 11083 Output Parameter: 11084 . A - the Galerkin coarse matrix 11085 11086 Options Database Key: 11087 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11088 11089 Level: developer 11090 11091 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11092 @*/ 11093 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11094 { 11095 IS zerorows; 11096 Vec diag; 11097 11098 PetscFunctionBegin; 11099 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11100 /* Construct the coarse grid matrix */ 11101 if (interpolate == restrct) { 11102 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11103 } else { 11104 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11105 } 11106 11107 /* If the interpolation matrix is not of full rank, A will have zero rows. 11108 This can legitimately happen in the case of non-nested geometric multigrid. 11109 In that event, we set the rows of the matrix to the rows of the identity, 11110 ignoring the equations (as the RHS will also be zero). */ 11111 11112 PetscCall(MatFindZeroRows(*A, &zerorows)); 11113 11114 if (zerorows != NULL) { /* if there are any zero rows */ 11115 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11116 PetscCall(MatGetDiagonal(*A, diag)); 11117 PetscCall(VecISSet(diag, zerorows, 1.0)); 11118 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11119 PetscCall(VecDestroy(&diag)); 11120 PetscCall(ISDestroy(&zerorows)); 11121 } 11122 PetscFunctionReturn(PETSC_SUCCESS); 11123 } 11124 11125 /*@C 11126 MatSetOperation - Allows user to set a matrix operation for any matrix type 11127 11128 Logically Collective 11129 11130 Input Parameters: 11131 + mat - the matrix 11132 . op - the name of the operation 11133 - f - the function that provides the operation 11134 11135 Level: developer 11136 11137 Example Usage: 11138 .vb 11139 extern PetscErrorCode usermult(Mat, Vec, Vec); 11140 11141 PetscCall(MatCreateXXX(comm, ..., &A)); 11142 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11143 .ve 11144 11145 Notes: 11146 See the file `include/petscmat.h` for a complete list of matrix 11147 operations, which all have the form MATOP_<OPERATION>, where 11148 <OPERATION> is the name (in all capital letters) of the 11149 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11150 11151 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11152 sequence as the usual matrix interface routines, since they 11153 are intended to be accessed via the usual matrix interface 11154 routines, e.g., 11155 .vb 11156 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11157 .ve 11158 11159 In particular each function MUST return `PETSC_SUCCESS` on success and 11160 nonzero on failure. 11161 11162 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11163 11164 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11165 @*/ 11166 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11167 { 11168 PetscFunctionBegin; 11169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11170 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11171 (((void (**)(void))mat->ops)[op]) = f; 11172 PetscFunctionReturn(PETSC_SUCCESS); 11173 } 11174 11175 /*@C 11176 MatGetOperation - Gets a matrix operation for any matrix type. 11177 11178 Not Collective 11179 11180 Input Parameters: 11181 + mat - the matrix 11182 - op - the name of the operation 11183 11184 Output Parameter: 11185 . f - the function that provides the operation 11186 11187 Level: developer 11188 11189 Example Usage: 11190 .vb 11191 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11192 11193 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11194 .ve 11195 11196 Notes: 11197 See the file include/petscmat.h for a complete list of matrix 11198 operations, which all have the form MATOP_<OPERATION>, where 11199 <OPERATION> is the name (in all capital letters) of the 11200 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11201 11202 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11203 11204 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11205 @*/ 11206 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11207 { 11208 PetscFunctionBegin; 11209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11210 *f = (((void (**)(void))mat->ops)[op]); 11211 PetscFunctionReturn(PETSC_SUCCESS); 11212 } 11213 11214 /*@ 11215 MatHasOperation - Determines whether the given matrix supports the particular operation. 11216 11217 Not Collective 11218 11219 Input Parameters: 11220 + mat - the matrix 11221 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11222 11223 Output Parameter: 11224 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11225 11226 Level: advanced 11227 11228 Note: 11229 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11230 11231 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11232 @*/ 11233 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11234 { 11235 PetscFunctionBegin; 11236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11237 PetscAssertPointer(has, 3); 11238 if (mat->ops->hasoperation) { 11239 PetscUseTypeMethod(mat, hasoperation, op, has); 11240 } else { 11241 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11242 else { 11243 *has = PETSC_FALSE; 11244 if (op == MATOP_CREATE_SUBMATRIX) { 11245 PetscMPIInt size; 11246 11247 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11248 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11249 } 11250 } 11251 } 11252 PetscFunctionReturn(PETSC_SUCCESS); 11253 } 11254 11255 /*@ 11256 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11257 11258 Collective 11259 11260 Input Parameter: 11261 . mat - the matrix 11262 11263 Output Parameter: 11264 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11265 11266 Level: beginner 11267 11268 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11269 @*/ 11270 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11271 { 11272 PetscFunctionBegin; 11273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11274 PetscValidType(mat, 1); 11275 PetscAssertPointer(cong, 2); 11276 if (!mat->rmap || !mat->cmap) { 11277 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11278 PetscFunctionReturn(PETSC_SUCCESS); 11279 } 11280 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11281 PetscCall(PetscLayoutSetUp(mat->rmap)); 11282 PetscCall(PetscLayoutSetUp(mat->cmap)); 11283 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11284 if (*cong) mat->congruentlayouts = 1; 11285 else mat->congruentlayouts = 0; 11286 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11287 PetscFunctionReturn(PETSC_SUCCESS); 11288 } 11289 11290 PetscErrorCode MatSetInf(Mat A) 11291 { 11292 PetscFunctionBegin; 11293 PetscUseTypeMethod(A, setinf); 11294 PetscFunctionReturn(PETSC_SUCCESS); 11295 } 11296 11297 /*@C 11298 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 11299 and possibly removes small values from the graph structure. 11300 11301 Collective 11302 11303 Input Parameters: 11304 + A - the matrix 11305 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11306 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11307 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11308 . num_idx - size of 'index' array 11309 - index - array of block indices to use for graph strength of connection weight 11310 11311 Output Parameter: 11312 . graph - the resulting graph 11313 11314 Level: advanced 11315 11316 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11317 @*/ 11318 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11319 { 11320 PetscFunctionBegin; 11321 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11322 PetscValidType(A, 1); 11323 PetscValidLogicalCollectiveBool(A, scale, 3); 11324 PetscAssertPointer(graph, 7); 11325 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11326 PetscFunctionReturn(PETSC_SUCCESS); 11327 } 11328 11329 /*@ 11330 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11331 meaning the same memory is used for the matrix, and no new memory is allocated. 11332 11333 Collective 11334 11335 Input Parameters: 11336 + A - the matrix 11337 - 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 11338 11339 Level: intermediate 11340 11341 Developer Note: 11342 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11343 of the arrays in the data structure are unneeded. 11344 11345 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11346 @*/ 11347 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11348 { 11349 PetscFunctionBegin; 11350 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11351 PetscUseTypeMethod(A, eliminatezeros, keep); 11352 PetscFunctionReturn(PETSC_SUCCESS); 11353 } 11354