1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n, st; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 207 PetscCall(MatGetSize(mat, &N, NULL)); 208 PetscCall(MatGetLocalSize(mat, &n, NULL)); 209 PetscCall(VecSet(l, 0.0)); 210 PetscCall(VecSetRandom(r, NULL)); 211 PetscCall(MatMult(mat, r, l)); 212 PetscCall(VecGetArrayRead(l, &al)); 213 } else { /* nonzero columns */ 214 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 215 PetscCall(MatGetSize(mat, NULL, &N)); 216 PetscCall(MatGetLocalSize(mat, NULL, &n)); 217 PetscCall(VecSet(r, 0.0)); 218 PetscCall(VecSetRandom(l, NULL)); 219 PetscCall(MatMultTranspose(mat, l, r)); 220 PetscCall(VecGetArrayRead(r, &al)); 221 } 222 if (tol <= 0.0) { 223 for (i = 0, nz = 0; i < n; i++) 224 if (al[i] != 0.0) nz++; 225 } else { 226 for (i = 0, nz = 0; i < n; i++) 227 if (PetscAbsScalar(al[i]) > tol) nz++; 228 } 229 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 230 if (gnz != N) { 231 PetscInt *nzr; 232 PetscCall(PetscMalloc1(nz, &nzr)); 233 if (nz) { 234 if (tol < 0) { 235 for (i = 0, nz = 0; i < n; i++) 236 if (al[i] != 0.0) nzr[nz++] = i + st; 237 } else { 238 for (i = 0, nz = 0; i < n; i++) 239 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 240 } 241 } 242 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 243 } else *nonzero = NULL; 244 if (!cols) { /* nonzero rows */ 245 PetscCall(VecRestoreArrayRead(l, &al)); 246 } else { 247 PetscCall(VecRestoreArrayRead(r, &al)); 248 } 249 PetscCall(VecDestroy(&l)); 250 PetscCall(VecDestroy(&r)); 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 /*@ 255 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 256 257 Input Parameter: 258 . mat - the matrix 259 260 Output Parameter: 261 . keptrows - the rows that are not completely zero 262 263 Level: intermediate 264 265 Note: 266 `keptrows` is set to `NULL` if all rows are nonzero. 267 268 .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 %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M); 2021 for (i = 0; i < n; i++) 2022 PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N); 2023 } 2024 if (mat->assembled) { 2025 mat->was_assembled = PETSC_TRUE; 2026 mat->assembled = PETSC_FALSE; 2027 } 2028 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2029 if (mat->ops->setvaluesblocked) { 2030 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2031 } else { 2032 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2033 PetscInt i, j, bs, cbs; 2034 2035 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2036 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2037 iidxm = buf; 2038 iidxn = buf + m * bs; 2039 } else { 2040 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2041 iidxm = bufr; 2042 iidxn = bufc; 2043 } 2044 for (i = 0; i < m; i++) { 2045 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2046 } 2047 if (m != n || bs != cbs || idxm != idxn) { 2048 for (i = 0; i < n; i++) { 2049 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2050 } 2051 } else iidxn = iidxm; 2052 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2053 PetscCall(PetscFree2(bufr, bufc)); 2054 } 2055 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2056 PetscFunctionReturn(PETSC_SUCCESS); 2057 } 2058 2059 /*@C 2060 MatGetValues - Gets a block of local values from a matrix. 2061 2062 Not Collective; can only return values that are owned by the give process 2063 2064 Input Parameters: 2065 + mat - the matrix 2066 . v - a logically two-dimensional array for storing the values 2067 . m - the number of rows 2068 . idxm - the global indices of the rows 2069 . n - the number of columns 2070 - idxn - the global indices of the columns 2071 2072 Level: advanced 2073 2074 Notes: 2075 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2076 The values, `v`, are then returned in a row-oriented format, 2077 analogous to that used by default in `MatSetValues()`. 2078 2079 `MatGetValues()` uses 0-based row and column numbers in 2080 Fortran as well as in C. 2081 2082 `MatGetValues()` requires that the matrix has been assembled 2083 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2084 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2085 without intermediate matrix assembly. 2086 2087 Negative row or column indices will be ignored and those locations in `v` will be 2088 left unchanged. 2089 2090 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2091 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2092 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2093 2094 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2095 @*/ 2096 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2097 { 2098 PetscFunctionBegin; 2099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2100 PetscValidType(mat, 1); 2101 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2102 PetscAssertPointer(idxm, 3); 2103 PetscAssertPointer(idxn, 5); 2104 PetscAssertPointer(v, 6); 2105 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2106 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2107 MatCheckPreallocated(mat, 1); 2108 2109 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2110 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2111 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2112 PetscFunctionReturn(PETSC_SUCCESS); 2113 } 2114 2115 /*@C 2116 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2117 defined previously by `MatSetLocalToGlobalMapping()` 2118 2119 Not Collective 2120 2121 Input Parameters: 2122 + mat - the matrix 2123 . nrow - number of rows 2124 . irow - the row local indices 2125 . ncol - number of columns 2126 - icol - the column local indices 2127 2128 Output Parameter: 2129 . y - a logically two-dimensional array of values 2130 2131 Level: advanced 2132 2133 Notes: 2134 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2135 2136 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, 2137 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2138 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2139 with `MatSetLocalToGlobalMapping()`. 2140 2141 Developer Note: 2142 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2143 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2144 2145 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2146 `MatSetValuesLocal()`, `MatGetValues()` 2147 @*/ 2148 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2149 { 2150 PetscFunctionBeginHot; 2151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2152 PetscValidType(mat, 1); 2153 MatCheckPreallocated(mat, 1); 2154 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2155 PetscAssertPointer(irow, 3); 2156 PetscAssertPointer(icol, 5); 2157 if (PetscDefined(USE_DEBUG)) { 2158 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2159 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2160 } 2161 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2162 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2163 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2164 else { 2165 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2166 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2167 irowm = buf; 2168 icolm = buf + nrow; 2169 } else { 2170 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2171 irowm = bufr; 2172 icolm = bufc; 2173 } 2174 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2175 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2176 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2177 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2178 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2179 PetscCall(PetscFree2(bufr, bufc)); 2180 } 2181 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2182 PetscFunctionReturn(PETSC_SUCCESS); 2183 } 2184 2185 /*@ 2186 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2187 the same size. Currently, this can only be called once and creates the given matrix. 2188 2189 Not Collective 2190 2191 Input Parameters: 2192 + mat - the matrix 2193 . nb - the number of blocks 2194 . bs - the number of rows (and columns) in each block 2195 . rows - a concatenation of the rows for each block 2196 - v - a concatenation of logically two-dimensional arrays of values 2197 2198 Level: advanced 2199 2200 Notes: 2201 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2202 2203 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2204 2205 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2206 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2207 @*/ 2208 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2209 { 2210 PetscFunctionBegin; 2211 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2212 PetscValidType(mat, 1); 2213 PetscAssertPointer(rows, 4); 2214 PetscAssertPointer(v, 5); 2215 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2216 2217 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2218 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2219 else { 2220 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2221 } 2222 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2223 PetscFunctionReturn(PETSC_SUCCESS); 2224 } 2225 2226 /*@ 2227 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2228 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2229 using a local (per-processor) numbering. 2230 2231 Not Collective 2232 2233 Input Parameters: 2234 + x - the matrix 2235 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2236 - cmapping - column mapping 2237 2238 Level: intermediate 2239 2240 Note: 2241 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2242 2243 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2244 @*/ 2245 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2246 { 2247 PetscFunctionBegin; 2248 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2249 PetscValidType(x, 1); 2250 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2251 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2252 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2253 else { 2254 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2255 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2256 } 2257 PetscFunctionReturn(PETSC_SUCCESS); 2258 } 2259 2260 /*@ 2261 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2262 2263 Not Collective 2264 2265 Input Parameter: 2266 . A - the matrix 2267 2268 Output Parameters: 2269 + rmapping - row mapping 2270 - cmapping - column mapping 2271 2272 Level: advanced 2273 2274 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2275 @*/ 2276 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2277 { 2278 PetscFunctionBegin; 2279 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2280 PetscValidType(A, 1); 2281 if (rmapping) { 2282 PetscAssertPointer(rmapping, 2); 2283 *rmapping = A->rmap->mapping; 2284 } 2285 if (cmapping) { 2286 PetscAssertPointer(cmapping, 3); 2287 *cmapping = A->cmap->mapping; 2288 } 2289 PetscFunctionReturn(PETSC_SUCCESS); 2290 } 2291 2292 /*@ 2293 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2294 2295 Logically Collective 2296 2297 Input Parameters: 2298 + A - the matrix 2299 . rmap - row layout 2300 - cmap - column layout 2301 2302 Level: advanced 2303 2304 Note: 2305 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2306 2307 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2308 @*/ 2309 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2310 { 2311 PetscFunctionBegin; 2312 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2313 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2314 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2315 PetscFunctionReturn(PETSC_SUCCESS); 2316 } 2317 2318 /*@ 2319 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2320 2321 Not Collective 2322 2323 Input Parameter: 2324 . A - the matrix 2325 2326 Output Parameters: 2327 + rmap - row layout 2328 - cmap - column layout 2329 2330 Level: advanced 2331 2332 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2333 @*/ 2334 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2335 { 2336 PetscFunctionBegin; 2337 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2338 PetscValidType(A, 1); 2339 if (rmap) { 2340 PetscAssertPointer(rmap, 2); 2341 *rmap = A->rmap; 2342 } 2343 if (cmap) { 2344 PetscAssertPointer(cmap, 3); 2345 *cmap = A->cmap; 2346 } 2347 PetscFunctionReturn(PETSC_SUCCESS); 2348 } 2349 2350 /*@C 2351 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2352 using a local numbering of the rows and columns. 2353 2354 Not Collective 2355 2356 Input Parameters: 2357 + mat - the matrix 2358 . nrow - number of rows 2359 . irow - the row local indices 2360 . ncol - number of columns 2361 . icol - the column local indices 2362 . y - a logically two-dimensional array of values 2363 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2364 2365 Level: intermediate 2366 2367 Notes: 2368 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2369 2370 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2371 options cannot be mixed without intervening calls to the assembly 2372 routines. 2373 2374 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2375 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2376 2377 Developer Note: 2378 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2379 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2380 2381 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2382 `MatGetValuesLocal()` 2383 @*/ 2384 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2385 { 2386 PetscFunctionBeginHot; 2387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2388 PetscValidType(mat, 1); 2389 MatCheckPreallocated(mat, 1); 2390 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2391 PetscAssertPointer(irow, 3); 2392 PetscAssertPointer(icol, 5); 2393 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2394 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2395 if (PetscDefined(USE_DEBUG)) { 2396 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2397 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2398 } 2399 2400 if (mat->assembled) { 2401 mat->was_assembled = PETSC_TRUE; 2402 mat->assembled = PETSC_FALSE; 2403 } 2404 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2405 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2406 else { 2407 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2408 const PetscInt *irowm, *icolm; 2409 2410 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2411 bufr = buf; 2412 bufc = buf + nrow; 2413 irowm = bufr; 2414 icolm = bufc; 2415 } else { 2416 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2417 irowm = bufr; 2418 icolm = bufc; 2419 } 2420 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2421 else irowm = irow; 2422 if (mat->cmap->mapping) { 2423 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2424 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2425 } else icolm = irowm; 2426 } else icolm = icol; 2427 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2428 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2429 } 2430 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2431 PetscFunctionReturn(PETSC_SUCCESS); 2432 } 2433 2434 /*@C 2435 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2436 using a local ordering of the nodes a block at a time. 2437 2438 Not Collective 2439 2440 Input Parameters: 2441 + mat - the matrix 2442 . nrow - number of rows 2443 . irow - the row local indices 2444 . ncol - number of columns 2445 . icol - the column local indices 2446 . y - a logically two-dimensional array of values 2447 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2448 2449 Level: intermediate 2450 2451 Notes: 2452 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2453 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2454 2455 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2456 options cannot be mixed without intervening calls to the assembly 2457 routines. 2458 2459 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2460 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2461 2462 Developer Note: 2463 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2464 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2465 2466 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2467 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2468 @*/ 2469 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2470 { 2471 PetscFunctionBeginHot; 2472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2473 PetscValidType(mat, 1); 2474 MatCheckPreallocated(mat, 1); 2475 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2476 PetscAssertPointer(irow, 3); 2477 PetscAssertPointer(icol, 5); 2478 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2479 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2480 if (PetscDefined(USE_DEBUG)) { 2481 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2482 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); 2483 } 2484 2485 if (mat->assembled) { 2486 mat->was_assembled = PETSC_TRUE; 2487 mat->assembled = PETSC_FALSE; 2488 } 2489 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2490 PetscInt irbs, rbs; 2491 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2492 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2493 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2494 } 2495 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2496 PetscInt icbs, cbs; 2497 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2498 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2499 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2500 } 2501 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2502 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2503 else { 2504 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2505 const PetscInt *irowm, *icolm; 2506 2507 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2508 bufr = buf; 2509 bufc = buf + nrow; 2510 irowm = bufr; 2511 icolm = bufc; 2512 } else { 2513 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2514 irowm = bufr; 2515 icolm = bufc; 2516 } 2517 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2518 else irowm = irow; 2519 if (mat->cmap->mapping) { 2520 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2521 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2522 } else icolm = irowm; 2523 } else icolm = icol; 2524 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2525 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2526 } 2527 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2528 PetscFunctionReturn(PETSC_SUCCESS); 2529 } 2530 2531 /*@ 2532 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2533 2534 Collective 2535 2536 Input Parameters: 2537 + mat - the matrix 2538 - x - the vector to be multiplied 2539 2540 Output Parameter: 2541 . y - the result 2542 2543 Level: developer 2544 2545 Note: 2546 The vectors `x` and `y` cannot be the same. I.e., one cannot 2547 call `MatMultDiagonalBlock`(A,y,y). 2548 2549 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2550 @*/ 2551 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2552 { 2553 PetscFunctionBegin; 2554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2555 PetscValidType(mat, 1); 2556 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2557 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2558 2559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2561 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2562 MatCheckPreallocated(mat, 1); 2563 2564 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2565 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2566 PetscFunctionReturn(PETSC_SUCCESS); 2567 } 2568 2569 /*@ 2570 MatMult - Computes the matrix-vector product, $y = Ax$. 2571 2572 Neighbor-wise Collective 2573 2574 Input Parameters: 2575 + mat - the matrix 2576 - x - the vector to be multiplied 2577 2578 Output Parameter: 2579 . y - the result 2580 2581 Level: beginner 2582 2583 Note: 2584 The vectors `x` and `y` cannot be the same. I.e., one cannot 2585 call `MatMult`(A,y,y). 2586 2587 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2588 @*/ 2589 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2590 { 2591 PetscFunctionBegin; 2592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2593 PetscValidType(mat, 1); 2594 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2595 VecCheckAssembled(x); 2596 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2597 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2598 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2599 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2600 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); 2601 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); 2602 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); 2603 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); 2604 PetscCall(VecSetErrorIfLocked(y, 3)); 2605 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2606 MatCheckPreallocated(mat, 1); 2607 2608 PetscCall(VecLockReadPush(x)); 2609 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2610 PetscUseTypeMethod(mat, mult, x, y); 2611 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2612 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2613 PetscCall(VecLockReadPop(x)); 2614 PetscFunctionReturn(PETSC_SUCCESS); 2615 } 2616 2617 /*@ 2618 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2619 2620 Neighbor-wise Collective 2621 2622 Input Parameters: 2623 + mat - the matrix 2624 - x - the vector to be multiplied 2625 2626 Output Parameter: 2627 . y - the result 2628 2629 Level: beginner 2630 2631 Notes: 2632 The vectors `x` and `y` cannot be the same. I.e., one cannot 2633 call `MatMultTranspose`(A,y,y). 2634 2635 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2636 use `MatMultHermitianTranspose()` 2637 2638 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2639 @*/ 2640 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2641 { 2642 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2643 2644 PetscFunctionBegin; 2645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2646 PetscValidType(mat, 1); 2647 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2648 VecCheckAssembled(x); 2649 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2650 2651 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2652 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2653 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2654 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); 2655 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); 2656 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); 2657 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); 2658 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2659 MatCheckPreallocated(mat, 1); 2660 2661 if (!mat->ops->multtranspose) { 2662 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2663 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); 2664 } else op = mat->ops->multtranspose; 2665 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2666 PetscCall(VecLockReadPush(x)); 2667 PetscCall((*op)(mat, x, y)); 2668 PetscCall(VecLockReadPop(x)); 2669 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2670 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2671 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2672 PetscFunctionReturn(PETSC_SUCCESS); 2673 } 2674 2675 /*@ 2676 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2677 2678 Neighbor-wise Collective 2679 2680 Input Parameters: 2681 + mat - the matrix 2682 - x - the vector to be multiplied 2683 2684 Output Parameter: 2685 . y - the result 2686 2687 Level: beginner 2688 2689 Notes: 2690 The vectors `x` and `y` cannot be the same. I.e., one cannot 2691 call `MatMultHermitianTranspose`(A,y,y). 2692 2693 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2694 2695 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2696 2697 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2698 @*/ 2699 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2700 { 2701 PetscFunctionBegin; 2702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2703 PetscValidType(mat, 1); 2704 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2705 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2706 2707 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2708 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2709 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2710 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2711 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2712 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2713 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2714 MatCheckPreallocated(mat, 1); 2715 2716 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2717 #if defined(PETSC_USE_COMPLEX) 2718 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2719 PetscCall(VecLockReadPush(x)); 2720 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2721 else PetscUseTypeMethod(mat, mult, x, y); 2722 PetscCall(VecLockReadPop(x)); 2723 } else { 2724 Vec w; 2725 PetscCall(VecDuplicate(x, &w)); 2726 PetscCall(VecCopy(x, w)); 2727 PetscCall(VecConjugate(w)); 2728 PetscCall(MatMultTranspose(mat, w, y)); 2729 PetscCall(VecDestroy(&w)); 2730 PetscCall(VecConjugate(y)); 2731 } 2732 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2733 #else 2734 PetscCall(MatMultTranspose(mat, x, y)); 2735 #endif 2736 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2737 PetscFunctionReturn(PETSC_SUCCESS); 2738 } 2739 2740 /*@ 2741 MatMultAdd - Computes $v3 = v2 + A * v1$. 2742 2743 Neighbor-wise Collective 2744 2745 Input Parameters: 2746 + mat - the matrix 2747 . v1 - the vector to be multiplied by `mat` 2748 - v2 - the vector to be added to the result 2749 2750 Output Parameter: 2751 . v3 - the result 2752 2753 Level: beginner 2754 2755 Note: 2756 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2757 call `MatMultAdd`(A,v1,v2,v1). 2758 2759 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2760 @*/ 2761 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2762 { 2763 PetscFunctionBegin; 2764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2765 PetscValidType(mat, 1); 2766 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2767 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2768 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2769 2770 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2771 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2772 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); 2773 /* 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); 2774 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); */ 2775 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); 2776 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); 2777 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2778 MatCheckPreallocated(mat, 1); 2779 2780 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2781 PetscCall(VecLockReadPush(v1)); 2782 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2783 PetscCall(VecLockReadPop(v1)); 2784 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2785 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2786 PetscFunctionReturn(PETSC_SUCCESS); 2787 } 2788 2789 /*@ 2790 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2791 2792 Neighbor-wise Collective 2793 2794 Input Parameters: 2795 + mat - the matrix 2796 . v1 - the vector to be multiplied by the transpose of the matrix 2797 - v2 - the vector to be added to the result 2798 2799 Output Parameter: 2800 . v3 - the result 2801 2802 Level: beginner 2803 2804 Note: 2805 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2806 call `MatMultTransposeAdd`(A,v1,v2,v1). 2807 2808 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2809 @*/ 2810 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2811 { 2812 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2813 2814 PetscFunctionBegin; 2815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2816 PetscValidType(mat, 1); 2817 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2818 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2819 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2820 2821 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2822 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2823 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); 2824 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); 2825 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); 2826 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2827 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2828 MatCheckPreallocated(mat, 1); 2829 2830 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2831 PetscCall(VecLockReadPush(v1)); 2832 PetscCall((*op)(mat, v1, v2, v3)); 2833 PetscCall(VecLockReadPop(v1)); 2834 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2835 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2836 PetscFunctionReturn(PETSC_SUCCESS); 2837 } 2838 2839 /*@ 2840 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2841 2842 Neighbor-wise Collective 2843 2844 Input Parameters: 2845 + mat - the matrix 2846 . v1 - the vector to be multiplied by the Hermitian transpose 2847 - v2 - the vector to be added to the result 2848 2849 Output Parameter: 2850 . v3 - the result 2851 2852 Level: beginner 2853 2854 Note: 2855 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2856 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2857 2858 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2859 @*/ 2860 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2861 { 2862 PetscFunctionBegin; 2863 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2864 PetscValidType(mat, 1); 2865 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2866 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2867 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2868 2869 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2870 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2871 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2872 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); 2873 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); 2874 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); 2875 MatCheckPreallocated(mat, 1); 2876 2877 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2878 PetscCall(VecLockReadPush(v1)); 2879 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2880 else { 2881 Vec w, z; 2882 PetscCall(VecDuplicate(v1, &w)); 2883 PetscCall(VecCopy(v1, w)); 2884 PetscCall(VecConjugate(w)); 2885 PetscCall(VecDuplicate(v3, &z)); 2886 PetscCall(MatMultTranspose(mat, w, z)); 2887 PetscCall(VecDestroy(&w)); 2888 PetscCall(VecConjugate(z)); 2889 if (v2 != v3) { 2890 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2891 } else { 2892 PetscCall(VecAXPY(v3, 1.0, z)); 2893 } 2894 PetscCall(VecDestroy(&z)); 2895 } 2896 PetscCall(VecLockReadPop(v1)); 2897 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2898 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2899 PetscFunctionReturn(PETSC_SUCCESS); 2900 } 2901 2902 /*@C 2903 MatGetFactorType - gets the type of factorization a matrix is 2904 2905 Not Collective 2906 2907 Input Parameter: 2908 . mat - the matrix 2909 2910 Output Parameter: 2911 . 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` 2912 2913 Level: intermediate 2914 2915 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2916 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2917 @*/ 2918 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2919 { 2920 PetscFunctionBegin; 2921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2922 PetscValidType(mat, 1); 2923 PetscAssertPointer(t, 2); 2924 *t = mat->factortype; 2925 PetscFunctionReturn(PETSC_SUCCESS); 2926 } 2927 2928 /*@C 2929 MatSetFactorType - sets the type of factorization a matrix is 2930 2931 Logically Collective 2932 2933 Input Parameters: 2934 + mat - the matrix 2935 - 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` 2936 2937 Level: intermediate 2938 2939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2940 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2941 @*/ 2942 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2943 { 2944 PetscFunctionBegin; 2945 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2946 PetscValidType(mat, 1); 2947 mat->factortype = t; 2948 PetscFunctionReturn(PETSC_SUCCESS); 2949 } 2950 2951 /*@C 2952 MatGetInfo - Returns information about matrix storage (number of 2953 nonzeros, memory, etc.). 2954 2955 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2956 2957 Input Parameters: 2958 + mat - the matrix 2959 - 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) 2960 2961 Output Parameter: 2962 . info - matrix information context 2963 2964 Options Database Key: 2965 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2966 2967 Notes: 2968 The `MatInfo` context contains a variety of matrix data, including 2969 number of nonzeros allocated and used, number of mallocs during 2970 matrix assembly, etc. Additional information for factored matrices 2971 is provided (such as the fill ratio, number of mallocs during 2972 factorization, etc.). 2973 2974 Example: 2975 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2976 data within the MatInfo context. For example, 2977 .vb 2978 MatInfo info; 2979 Mat A; 2980 double mal, nz_a, nz_u; 2981 2982 MatGetInfo(A, MAT_LOCAL, &info); 2983 mal = info.mallocs; 2984 nz_a = info.nz_allocated; 2985 .ve 2986 2987 Fortran users should declare info as a double precision 2988 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2989 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2990 a complete list of parameter names. 2991 .vb 2992 double precision info(MAT_INFO_SIZE) 2993 double precision mal, nz_a 2994 Mat A 2995 integer ierr 2996 2997 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2998 mal = info(MAT_INFO_MALLOCS) 2999 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3000 .ve 3001 3002 Level: intermediate 3003 3004 Developer Note: 3005 The Fortran interface is not autogenerated as the 3006 interface definition cannot be generated correctly [due to `MatInfo` argument] 3007 3008 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3009 @*/ 3010 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3011 { 3012 PetscFunctionBegin; 3013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3014 PetscValidType(mat, 1); 3015 PetscAssertPointer(info, 3); 3016 MatCheckPreallocated(mat, 1); 3017 PetscUseTypeMethod(mat, getinfo, flag, info); 3018 PetscFunctionReturn(PETSC_SUCCESS); 3019 } 3020 3021 /* 3022 This is used by external packages where it is not easy to get the info from the actual 3023 matrix factorization. 3024 */ 3025 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3026 { 3027 PetscFunctionBegin; 3028 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3029 PetscFunctionReturn(PETSC_SUCCESS); 3030 } 3031 3032 /*@C 3033 MatLUFactor - Performs in-place LU factorization of matrix. 3034 3035 Collective 3036 3037 Input Parameters: 3038 + mat - the matrix 3039 . row - row permutation 3040 . col - column permutation 3041 - info - options for factorization, includes 3042 .vb 3043 fill - expected fill as ratio of original fill. 3044 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3045 Run with the option -info to determine an optimal value to use 3046 .ve 3047 3048 Level: developer 3049 3050 Notes: 3051 Most users should employ the `KSP` interface for linear solvers 3052 instead of working directly with matrix algebra routines such as this. 3053 See, e.g., `KSPCreate()`. 3054 3055 This changes the state of the matrix to a factored matrix; it cannot be used 3056 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3057 3058 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3059 when not using `KSP`. 3060 3061 Developer Note: 3062 The Fortran interface is not autogenerated as the 3063 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3064 3065 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3066 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3067 @*/ 3068 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3069 { 3070 MatFactorInfo tinfo; 3071 3072 PetscFunctionBegin; 3073 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3074 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3075 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3076 if (info) PetscAssertPointer(info, 4); 3077 PetscValidType(mat, 1); 3078 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3079 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3080 MatCheckPreallocated(mat, 1); 3081 if (!info) { 3082 PetscCall(MatFactorInfoInitialize(&tinfo)); 3083 info = &tinfo; 3084 } 3085 3086 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3087 PetscUseTypeMethod(mat, lufactor, row, col, info); 3088 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3089 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3090 PetscFunctionReturn(PETSC_SUCCESS); 3091 } 3092 3093 /*@C 3094 MatILUFactor - Performs in-place ILU factorization of matrix. 3095 3096 Collective 3097 3098 Input Parameters: 3099 + mat - the matrix 3100 . row - row permutation 3101 . col - column permutation 3102 - info - structure containing 3103 .vb 3104 levels - number of levels of fill. 3105 expected fill - as ratio of original fill. 3106 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3107 missing diagonal entries) 3108 .ve 3109 3110 Level: developer 3111 3112 Notes: 3113 Most users should employ the `KSP` interface for linear solvers 3114 instead of working directly with matrix algebra routines such as this. 3115 See, e.g., `KSPCreate()`. 3116 3117 Probably really in-place only when level of fill is zero, otherwise allocates 3118 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3119 when not using `KSP`. 3120 3121 Developer Note: 3122 The Fortran interface is not autogenerated as the 3123 interface definition cannot be generated correctly [due to MatFactorInfo] 3124 3125 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3126 @*/ 3127 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3128 { 3129 PetscFunctionBegin; 3130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3131 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3132 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3133 PetscAssertPointer(info, 4); 3134 PetscValidType(mat, 1); 3135 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3136 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3137 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3138 MatCheckPreallocated(mat, 1); 3139 3140 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3141 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3142 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3143 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3144 PetscFunctionReturn(PETSC_SUCCESS); 3145 } 3146 3147 /*@C 3148 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3149 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3150 3151 Collective 3152 3153 Input Parameters: 3154 + fact - the factor matrix obtained with `MatGetFactor()` 3155 . mat - the matrix 3156 . row - the row permutation 3157 . col - the column permutation 3158 - info - options for factorization, includes 3159 .vb 3160 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3161 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3162 .ve 3163 3164 Level: developer 3165 3166 Notes: 3167 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3168 3169 Most users should employ the simplified `KSP` interface for linear solvers 3170 instead of working directly with matrix algebra routines such as this. 3171 See, e.g., `KSPCreate()`. 3172 3173 Developer Note: 3174 The Fortran interface is not autogenerated as the 3175 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3176 3177 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3178 @*/ 3179 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3180 { 3181 MatFactorInfo tinfo; 3182 3183 PetscFunctionBegin; 3184 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3186 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3187 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3188 if (info) PetscAssertPointer(info, 5); 3189 PetscValidType(fact, 1); 3190 PetscValidType(mat, 2); 3191 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3192 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3193 MatCheckPreallocated(mat, 2); 3194 if (!info) { 3195 PetscCall(MatFactorInfoInitialize(&tinfo)); 3196 info = &tinfo; 3197 } 3198 3199 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3200 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3201 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3202 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3203 PetscFunctionReturn(PETSC_SUCCESS); 3204 } 3205 3206 /*@C 3207 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3208 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3209 3210 Collective 3211 3212 Input Parameters: 3213 + fact - the factor matrix obtained with `MatGetFactor()` 3214 . mat - the matrix 3215 - info - options for factorization 3216 3217 Level: developer 3218 3219 Notes: 3220 See `MatLUFactor()` for in-place factorization. See 3221 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3222 3223 Most users should employ the `KSP` interface for linear solvers 3224 instead of working directly with matrix algebra routines such as this. 3225 See, e.g., `KSPCreate()`. 3226 3227 Developer Note: 3228 The Fortran interface is not autogenerated as the 3229 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3230 3231 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3232 @*/ 3233 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3234 { 3235 MatFactorInfo tinfo; 3236 3237 PetscFunctionBegin; 3238 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3239 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3240 PetscValidType(fact, 1); 3241 PetscValidType(mat, 2); 3242 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3243 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, 3244 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3245 3246 MatCheckPreallocated(mat, 2); 3247 if (!info) { 3248 PetscCall(MatFactorInfoInitialize(&tinfo)); 3249 info = &tinfo; 3250 } 3251 3252 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3253 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3254 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3255 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3256 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3257 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3258 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3259 PetscFunctionReturn(PETSC_SUCCESS); 3260 } 3261 3262 /*@C 3263 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3264 symmetric matrix. 3265 3266 Collective 3267 3268 Input Parameters: 3269 + mat - the matrix 3270 . perm - row and column permutations 3271 - info - expected fill as ratio of original fill 3272 3273 Level: developer 3274 3275 Notes: 3276 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3277 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3278 3279 Most users should employ the `KSP` interface for linear solvers 3280 instead of working directly with matrix algebra routines such as this. 3281 See, e.g., `KSPCreate()`. 3282 3283 Developer Note: 3284 The Fortran interface is not autogenerated as the 3285 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3286 3287 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3288 `MatGetOrdering()` 3289 @*/ 3290 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3291 { 3292 MatFactorInfo tinfo; 3293 3294 PetscFunctionBegin; 3295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3296 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3297 if (info) PetscAssertPointer(info, 3); 3298 PetscValidType(mat, 1); 3299 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3301 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3302 MatCheckPreallocated(mat, 1); 3303 if (!info) { 3304 PetscCall(MatFactorInfoInitialize(&tinfo)); 3305 info = &tinfo; 3306 } 3307 3308 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3309 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3310 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3311 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3312 PetscFunctionReturn(PETSC_SUCCESS); 3313 } 3314 3315 /*@C 3316 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3317 of a symmetric matrix. 3318 3319 Collective 3320 3321 Input Parameters: 3322 + fact - the factor matrix obtained with `MatGetFactor()` 3323 . mat - the matrix 3324 . perm - row and column permutations 3325 - info - options for factorization, includes 3326 .vb 3327 fill - expected fill as ratio of original fill. 3328 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3329 Run with the option -info to determine an optimal value to use 3330 .ve 3331 3332 Level: developer 3333 3334 Notes: 3335 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3336 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3337 3338 Most users should employ the `KSP` interface for linear solvers 3339 instead of working directly with matrix algebra routines such as this. 3340 See, e.g., `KSPCreate()`. 3341 3342 Developer Note: 3343 The Fortran interface is not autogenerated as the 3344 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3345 3346 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3347 `MatGetOrdering()` 3348 @*/ 3349 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3350 { 3351 MatFactorInfo tinfo; 3352 3353 PetscFunctionBegin; 3354 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3355 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3356 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3357 if (info) PetscAssertPointer(info, 4); 3358 PetscValidType(fact, 1); 3359 PetscValidType(mat, 2); 3360 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3361 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3362 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3363 MatCheckPreallocated(mat, 2); 3364 if (!info) { 3365 PetscCall(MatFactorInfoInitialize(&tinfo)); 3366 info = &tinfo; 3367 } 3368 3369 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3370 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3371 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3372 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3373 PetscFunctionReturn(PETSC_SUCCESS); 3374 } 3375 3376 /*@C 3377 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3378 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3379 `MatCholeskyFactorSymbolic()`. 3380 3381 Collective 3382 3383 Input Parameters: 3384 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3385 . mat - the initial matrix that is to be factored 3386 - info - options for factorization 3387 3388 Level: developer 3389 3390 Note: 3391 Most users should employ the `KSP` interface for linear solvers 3392 instead of working directly with matrix algebra routines such as this. 3393 See, e.g., `KSPCreate()`. 3394 3395 Developer Note: 3396 The Fortran interface is not autogenerated as the 3397 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3398 3399 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3400 @*/ 3401 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3402 { 3403 MatFactorInfo tinfo; 3404 3405 PetscFunctionBegin; 3406 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3407 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3408 PetscValidType(fact, 1); 3409 PetscValidType(mat, 2); 3410 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3411 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, 3412 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3413 MatCheckPreallocated(mat, 2); 3414 if (!info) { 3415 PetscCall(MatFactorInfoInitialize(&tinfo)); 3416 info = &tinfo; 3417 } 3418 3419 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3420 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3421 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3422 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3423 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3424 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3425 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3426 PetscFunctionReturn(PETSC_SUCCESS); 3427 } 3428 3429 /*@ 3430 MatQRFactor - Performs in-place QR factorization of matrix. 3431 3432 Collective 3433 3434 Input Parameters: 3435 + mat - the matrix 3436 . col - column permutation 3437 - info - options for factorization, includes 3438 .vb 3439 fill - expected fill as ratio of original fill. 3440 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3441 Run with the option -info to determine an optimal value to use 3442 .ve 3443 3444 Level: developer 3445 3446 Notes: 3447 Most users should employ the `KSP` interface for linear solvers 3448 instead of working directly with matrix algebra routines such as this. 3449 See, e.g., `KSPCreate()`. 3450 3451 This changes the state of the matrix to a factored matrix; it cannot be used 3452 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3453 3454 Developer Note: 3455 The Fortran interface is not autogenerated as the 3456 interface definition cannot be generated correctly [due to MatFactorInfo] 3457 3458 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3459 `MatSetUnfactored()` 3460 @*/ 3461 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3462 { 3463 PetscFunctionBegin; 3464 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3465 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3466 if (info) PetscAssertPointer(info, 3); 3467 PetscValidType(mat, 1); 3468 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3469 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3470 MatCheckPreallocated(mat, 1); 3471 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3472 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3473 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3474 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3475 PetscFunctionReturn(PETSC_SUCCESS); 3476 } 3477 3478 /*@ 3479 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3480 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3481 3482 Collective 3483 3484 Input Parameters: 3485 + fact - the factor matrix obtained with `MatGetFactor()` 3486 . mat - the matrix 3487 . col - column permutation 3488 - info - options for factorization, includes 3489 .vb 3490 fill - expected fill as ratio of original fill. 3491 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3492 Run with the option -info to determine an optimal value to use 3493 .ve 3494 3495 Level: developer 3496 3497 Note: 3498 Most users should employ the `KSP` interface for linear solvers 3499 instead of working directly with matrix algebra routines such as this. 3500 See, e.g., `KSPCreate()`. 3501 3502 Developer Note: 3503 The Fortran interface is not autogenerated as the 3504 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3505 3506 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3507 @*/ 3508 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3509 { 3510 MatFactorInfo tinfo; 3511 3512 PetscFunctionBegin; 3513 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3515 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3516 if (info) PetscAssertPointer(info, 4); 3517 PetscValidType(fact, 1); 3518 PetscValidType(mat, 2); 3519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3520 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3521 MatCheckPreallocated(mat, 2); 3522 if (!info) { 3523 PetscCall(MatFactorInfoInitialize(&tinfo)); 3524 info = &tinfo; 3525 } 3526 3527 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3528 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3529 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3530 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3531 PetscFunctionReturn(PETSC_SUCCESS); 3532 } 3533 3534 /*@ 3535 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3536 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3537 3538 Collective 3539 3540 Input Parameters: 3541 + fact - the factor matrix obtained with `MatGetFactor()` 3542 . mat - the matrix 3543 - info - options for factorization 3544 3545 Level: developer 3546 3547 Notes: 3548 See `MatQRFactor()` for in-place factorization. 3549 3550 Most users should employ the `KSP` interface for linear solvers 3551 instead of working directly with matrix algebra routines such as this. 3552 See, e.g., `KSPCreate()`. 3553 3554 Developer Note: 3555 The Fortran interface is not autogenerated as the 3556 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3557 3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3559 @*/ 3560 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3561 { 3562 MatFactorInfo tinfo; 3563 3564 PetscFunctionBegin; 3565 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3567 PetscValidType(fact, 1); 3568 PetscValidType(mat, 2); 3569 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3570 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, 3571 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3572 3573 MatCheckPreallocated(mat, 2); 3574 if (!info) { 3575 PetscCall(MatFactorInfoInitialize(&tinfo)); 3576 info = &tinfo; 3577 } 3578 3579 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3580 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3581 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3582 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3583 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3584 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3585 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3586 PetscFunctionReturn(PETSC_SUCCESS); 3587 } 3588 3589 /*@ 3590 MatSolve - Solves $A x = b$, given a factored matrix. 3591 3592 Neighbor-wise Collective 3593 3594 Input Parameters: 3595 + mat - the factored matrix 3596 - b - the right-hand-side vector 3597 3598 Output Parameter: 3599 . x - the result vector 3600 3601 Level: developer 3602 3603 Notes: 3604 The vectors `b` and `x` cannot be the same. I.e., one cannot 3605 call `MatSolve`(A,x,x). 3606 3607 Most users should employ the `KSP` interface for linear solvers 3608 instead of working directly with matrix algebra routines such as this. 3609 See, e.g., `KSPCreate()`. 3610 3611 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3612 @*/ 3613 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3614 { 3615 PetscFunctionBegin; 3616 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3617 PetscValidType(mat, 1); 3618 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3619 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3620 PetscCheckSameComm(mat, 1, b, 2); 3621 PetscCheckSameComm(mat, 1, x, 3); 3622 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3623 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); 3624 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); 3625 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); 3626 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3627 MatCheckPreallocated(mat, 1); 3628 3629 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3630 if (mat->factorerrortype) { 3631 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3632 PetscCall(VecSetInf(x)); 3633 } else PetscUseTypeMethod(mat, solve, b, x); 3634 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3635 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3636 PetscFunctionReturn(PETSC_SUCCESS); 3637 } 3638 3639 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3640 { 3641 Vec b, x; 3642 PetscInt N, i; 3643 PetscErrorCode (*f)(Mat, Vec, Vec); 3644 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3645 3646 PetscFunctionBegin; 3647 if (A->factorerrortype) { 3648 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3649 PetscCall(MatSetInf(X)); 3650 PetscFunctionReturn(PETSC_SUCCESS); 3651 } 3652 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3653 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3654 PetscCall(MatBoundToCPU(A, &Abound)); 3655 if (!Abound) { 3656 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3657 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3658 } 3659 #if PetscDefined(HAVE_CUDA) 3660 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3661 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3662 #elif PetscDefined(HAVE_HIP) 3663 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3664 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3665 #endif 3666 PetscCall(MatGetSize(B, NULL, &N)); 3667 for (i = 0; i < N; i++) { 3668 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3669 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3670 PetscCall((*f)(A, b, x)); 3671 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3672 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3673 } 3674 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3675 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3676 PetscFunctionReturn(PETSC_SUCCESS); 3677 } 3678 3679 /*@ 3680 MatMatSolve - Solves $A X = B$, given a factored matrix. 3681 3682 Neighbor-wise Collective 3683 3684 Input Parameters: 3685 + A - the factored matrix 3686 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3687 3688 Output Parameter: 3689 . X - the result matrix (dense matrix) 3690 3691 Level: developer 3692 3693 Note: 3694 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3695 otherwise, `B` and `X` cannot be the same. 3696 3697 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3698 @*/ 3699 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3700 { 3701 PetscFunctionBegin; 3702 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3703 PetscValidType(A, 1); 3704 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3705 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3706 PetscCheckSameComm(A, 1, B, 2); 3707 PetscCheckSameComm(A, 1, X, 3); 3708 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); 3709 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); 3710 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"); 3711 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3712 MatCheckPreallocated(A, 1); 3713 3714 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3715 if (!A->ops->matsolve) { 3716 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3717 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3718 } else PetscUseTypeMethod(A, matsolve, B, X); 3719 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3720 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3721 PetscFunctionReturn(PETSC_SUCCESS); 3722 } 3723 3724 /*@ 3725 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3726 3727 Neighbor-wise Collective 3728 3729 Input Parameters: 3730 + A - the factored matrix 3731 - B - the right-hand-side matrix (`MATDENSE` matrix) 3732 3733 Output Parameter: 3734 . X - the result matrix (dense matrix) 3735 3736 Level: developer 3737 3738 Note: 3739 The matrices `B` and `X` cannot be the same. I.e., one cannot 3740 call `MatMatSolveTranspose`(A,X,X). 3741 3742 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3743 @*/ 3744 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3745 { 3746 PetscFunctionBegin; 3747 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3748 PetscValidType(A, 1); 3749 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3750 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3751 PetscCheckSameComm(A, 1, B, 2); 3752 PetscCheckSameComm(A, 1, X, 3); 3753 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3754 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); 3755 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); 3756 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); 3757 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"); 3758 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3759 MatCheckPreallocated(A, 1); 3760 3761 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3762 if (!A->ops->matsolvetranspose) { 3763 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3764 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3765 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3766 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3767 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3768 PetscFunctionReturn(PETSC_SUCCESS); 3769 } 3770 3771 /*@ 3772 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3773 3774 Neighbor-wise Collective 3775 3776 Input Parameters: 3777 + A - the factored matrix 3778 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3779 3780 Output Parameter: 3781 . X - the result matrix (dense matrix) 3782 3783 Level: developer 3784 3785 Note: 3786 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 3787 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3788 3789 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3790 @*/ 3791 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3792 { 3793 PetscFunctionBegin; 3794 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3795 PetscValidType(A, 1); 3796 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3797 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3798 PetscCheckSameComm(A, 1, Bt, 2); 3799 PetscCheckSameComm(A, 1, X, 3); 3800 3801 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3802 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); 3803 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); 3804 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"); 3805 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3806 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3807 MatCheckPreallocated(A, 1); 3808 3809 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3810 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3811 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3812 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3813 PetscFunctionReturn(PETSC_SUCCESS); 3814 } 3815 3816 /*@ 3817 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3818 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3819 3820 Neighbor-wise Collective 3821 3822 Input Parameters: 3823 + mat - the factored matrix 3824 - b - the right-hand-side vector 3825 3826 Output Parameter: 3827 . x - the result vector 3828 3829 Level: developer 3830 3831 Notes: 3832 `MatSolve()` should be used for most applications, as it performs 3833 a forward solve followed by a backward solve. 3834 3835 The vectors `b` and `x` cannot be the same, i.e., one cannot 3836 call `MatForwardSolve`(A,x,x). 3837 3838 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3839 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3840 `MatForwardSolve()` solves $U^T*D y = b$, and 3841 `MatBackwardSolve()` solves $U x = y$. 3842 Thus they do not provide a symmetric preconditioner. 3843 3844 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3845 @*/ 3846 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3847 { 3848 PetscFunctionBegin; 3849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3850 PetscValidType(mat, 1); 3851 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3852 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3853 PetscCheckSameComm(mat, 1, b, 2); 3854 PetscCheckSameComm(mat, 1, x, 3); 3855 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3856 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); 3857 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); 3858 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); 3859 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3860 MatCheckPreallocated(mat, 1); 3861 3862 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3863 PetscUseTypeMethod(mat, forwardsolve, b, x); 3864 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3865 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3866 PetscFunctionReturn(PETSC_SUCCESS); 3867 } 3868 3869 /*@ 3870 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3871 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3872 3873 Neighbor-wise Collective 3874 3875 Input Parameters: 3876 + mat - the factored matrix 3877 - b - the right-hand-side vector 3878 3879 Output Parameter: 3880 . x - the result vector 3881 3882 Level: developer 3883 3884 Notes: 3885 `MatSolve()` should be used for most applications, as it performs 3886 a forward solve followed by a backward solve. 3887 3888 The vectors `b` and `x` cannot be the same. I.e., one cannot 3889 call `MatBackwardSolve`(A,x,x). 3890 3891 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3892 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3893 `MatForwardSolve()` solves $U^T*D y = b$, and 3894 `MatBackwardSolve()` solves $U x = y$. 3895 Thus they do not provide a symmetric preconditioner. 3896 3897 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3898 @*/ 3899 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3900 { 3901 PetscFunctionBegin; 3902 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3903 PetscValidType(mat, 1); 3904 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3905 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3906 PetscCheckSameComm(mat, 1, b, 2); 3907 PetscCheckSameComm(mat, 1, x, 3); 3908 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3909 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); 3910 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); 3911 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); 3912 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3913 MatCheckPreallocated(mat, 1); 3914 3915 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3916 PetscUseTypeMethod(mat, backwardsolve, b, x); 3917 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3918 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3919 PetscFunctionReturn(PETSC_SUCCESS); 3920 } 3921 3922 /*@ 3923 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3924 3925 Neighbor-wise Collective 3926 3927 Input Parameters: 3928 + mat - the factored matrix 3929 . b - the right-hand-side vector 3930 - y - the vector to be added to 3931 3932 Output Parameter: 3933 . x - the result vector 3934 3935 Level: developer 3936 3937 Note: 3938 The vectors `b` and `x` cannot be the same. I.e., one cannot 3939 call `MatSolveAdd`(A,x,y,x). 3940 3941 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3942 @*/ 3943 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3944 { 3945 PetscScalar one = 1.0; 3946 Vec tmp; 3947 3948 PetscFunctionBegin; 3949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3950 PetscValidType(mat, 1); 3951 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3952 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3953 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3954 PetscCheckSameComm(mat, 1, b, 2); 3955 PetscCheckSameComm(mat, 1, y, 3); 3956 PetscCheckSameComm(mat, 1, x, 4); 3957 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3958 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); 3959 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); 3960 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); 3961 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); 3962 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); 3963 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3964 MatCheckPreallocated(mat, 1); 3965 3966 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3967 if (mat->factorerrortype) { 3968 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3969 PetscCall(VecSetInf(x)); 3970 } else if (mat->ops->solveadd) { 3971 PetscUseTypeMethod(mat, solveadd, b, y, x); 3972 } else { 3973 /* do the solve then the add manually */ 3974 if (x != y) { 3975 PetscCall(MatSolve(mat, b, x)); 3976 PetscCall(VecAXPY(x, one, y)); 3977 } else { 3978 PetscCall(VecDuplicate(x, &tmp)); 3979 PetscCall(VecCopy(x, tmp)); 3980 PetscCall(MatSolve(mat, b, x)); 3981 PetscCall(VecAXPY(x, one, tmp)); 3982 PetscCall(VecDestroy(&tmp)); 3983 } 3984 } 3985 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3986 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3987 PetscFunctionReturn(PETSC_SUCCESS); 3988 } 3989 3990 /*@ 3991 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 3992 3993 Neighbor-wise Collective 3994 3995 Input Parameters: 3996 + mat - the factored matrix 3997 - b - the right-hand-side vector 3998 3999 Output Parameter: 4000 . x - the result vector 4001 4002 Level: developer 4003 4004 Notes: 4005 The vectors `b` and `x` cannot be the same. I.e., one cannot 4006 call `MatSolveTranspose`(A,x,x). 4007 4008 Most users should employ the `KSP` interface for linear solvers 4009 instead of working directly with matrix algebra routines such as this. 4010 See, e.g., `KSPCreate()`. 4011 4012 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4013 @*/ 4014 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4015 { 4016 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4017 4018 PetscFunctionBegin; 4019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4020 PetscValidType(mat, 1); 4021 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4022 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4023 PetscCheckSameComm(mat, 1, b, 2); 4024 PetscCheckSameComm(mat, 1, x, 3); 4025 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4026 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); 4027 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); 4028 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4029 MatCheckPreallocated(mat, 1); 4030 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4031 if (mat->factorerrortype) { 4032 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4033 PetscCall(VecSetInf(x)); 4034 } else { 4035 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4036 PetscCall((*f)(mat, b, x)); 4037 } 4038 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4039 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4040 PetscFunctionReturn(PETSC_SUCCESS); 4041 } 4042 4043 /*@ 4044 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4045 factored matrix. 4046 4047 Neighbor-wise Collective 4048 4049 Input Parameters: 4050 + mat - the factored matrix 4051 . b - the right-hand-side vector 4052 - y - the vector to be added to 4053 4054 Output Parameter: 4055 . x - the result vector 4056 4057 Level: developer 4058 4059 Note: 4060 The vectors `b` and `x` cannot be the same. I.e., one cannot 4061 call `MatSolveTransposeAdd`(A,x,y,x). 4062 4063 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4064 @*/ 4065 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4066 { 4067 PetscScalar one = 1.0; 4068 Vec tmp; 4069 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4070 4071 PetscFunctionBegin; 4072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4073 PetscValidType(mat, 1); 4074 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4075 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4076 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4077 PetscCheckSameComm(mat, 1, b, 2); 4078 PetscCheckSameComm(mat, 1, y, 3); 4079 PetscCheckSameComm(mat, 1, x, 4); 4080 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4081 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); 4082 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); 4083 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); 4084 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); 4085 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4086 MatCheckPreallocated(mat, 1); 4087 4088 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4089 if (mat->factorerrortype) { 4090 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4091 PetscCall(VecSetInf(x)); 4092 } else if (f) { 4093 PetscCall((*f)(mat, b, y, x)); 4094 } else { 4095 /* do the solve then the add manually */ 4096 if (x != y) { 4097 PetscCall(MatSolveTranspose(mat, b, x)); 4098 PetscCall(VecAXPY(x, one, y)); 4099 } else { 4100 PetscCall(VecDuplicate(x, &tmp)); 4101 PetscCall(VecCopy(x, tmp)); 4102 PetscCall(MatSolveTranspose(mat, b, x)); 4103 PetscCall(VecAXPY(x, one, tmp)); 4104 PetscCall(VecDestroy(&tmp)); 4105 } 4106 } 4107 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4108 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4109 PetscFunctionReturn(PETSC_SUCCESS); 4110 } 4111 4112 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4113 /*@ 4114 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4115 4116 Neighbor-wise Collective 4117 4118 Input Parameters: 4119 + mat - the matrix 4120 . b - the right-hand side 4121 . omega - the relaxation factor 4122 . flag - flag indicating the type of SOR (see below) 4123 . shift - diagonal shift 4124 . its - the number of iterations 4125 - lits - the number of local iterations 4126 4127 Output Parameter: 4128 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4129 4130 SOR Flags: 4131 + `SOR_FORWARD_SWEEP` - forward SOR 4132 . `SOR_BACKWARD_SWEEP` - backward SOR 4133 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4134 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4135 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4136 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4137 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4138 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4139 upper/lower triangular part of matrix to 4140 vector (with omega) 4141 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4142 4143 Level: developer 4144 4145 Notes: 4146 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4147 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4148 on each processor. 4149 4150 Application programmers will not generally use `MatSOR()` directly, 4151 but instead will employ the `KSP`/`PC` interface. 4152 4153 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4154 4155 Most users should employ the `KSP` interface for linear solvers 4156 instead of working directly with matrix algebra routines such as this. 4157 See, e.g., `KSPCreate()`. 4158 4159 Vectors `x` and `b` CANNOT be the same 4160 4161 The flags are implemented as bitwise inclusive or operations. 4162 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4163 to specify a zero initial guess for SSOR. 4164 4165 Developer Note: 4166 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4167 4168 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4169 @*/ 4170 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4171 { 4172 PetscFunctionBegin; 4173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4174 PetscValidType(mat, 1); 4175 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4176 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4177 PetscCheckSameComm(mat, 1, b, 2); 4178 PetscCheckSameComm(mat, 1, x, 8); 4179 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4180 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4181 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); 4182 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); 4183 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); 4184 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4185 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4186 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4187 4188 MatCheckPreallocated(mat, 1); 4189 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4190 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4191 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4192 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4193 PetscFunctionReturn(PETSC_SUCCESS); 4194 } 4195 4196 /* 4197 Default matrix copy routine. 4198 */ 4199 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4200 { 4201 PetscInt i, rstart = 0, rend = 0, nz; 4202 const PetscInt *cwork; 4203 const PetscScalar *vwork; 4204 4205 PetscFunctionBegin; 4206 if (B->assembled) PetscCall(MatZeroEntries(B)); 4207 if (str == SAME_NONZERO_PATTERN) { 4208 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4209 for (i = rstart; i < rend; i++) { 4210 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4211 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4212 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4213 } 4214 } else { 4215 PetscCall(MatAYPX(B, 0.0, A, str)); 4216 } 4217 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4218 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4219 PetscFunctionReturn(PETSC_SUCCESS); 4220 } 4221 4222 /*@ 4223 MatCopy - Copies a matrix to another matrix. 4224 4225 Collective 4226 4227 Input Parameters: 4228 + A - the matrix 4229 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4230 4231 Output Parameter: 4232 . B - where the copy is put 4233 4234 Level: intermediate 4235 4236 Notes: 4237 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4238 4239 `MatCopy()` copies the matrix entries of a matrix to another existing 4240 matrix (after first zeroing the second matrix). A related routine is 4241 `MatConvert()`, which first creates a new matrix and then copies the data. 4242 4243 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4244 @*/ 4245 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4246 { 4247 PetscInt i; 4248 4249 PetscFunctionBegin; 4250 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4251 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4252 PetscValidType(A, 1); 4253 PetscValidType(B, 2); 4254 PetscCheckSameComm(A, 1, B, 2); 4255 MatCheckPreallocated(B, 2); 4256 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4257 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4258 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, 4259 A->cmap->N, B->cmap->N); 4260 MatCheckPreallocated(A, 1); 4261 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4262 4263 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4264 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4265 else PetscCall(MatCopy_Basic(A, B, str)); 4266 4267 B->stencil.dim = A->stencil.dim; 4268 B->stencil.noc = A->stencil.noc; 4269 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4270 B->stencil.dims[i] = A->stencil.dims[i]; 4271 B->stencil.starts[i] = A->stencil.starts[i]; 4272 } 4273 4274 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4275 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4276 PetscFunctionReturn(PETSC_SUCCESS); 4277 } 4278 4279 /*@C 4280 MatConvert - Converts a matrix to another matrix, either of the same 4281 or different type. 4282 4283 Collective 4284 4285 Input Parameters: 4286 + mat - the matrix 4287 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4288 same type as the original matrix. 4289 - reuse - denotes if the destination matrix is to be created or reused. 4290 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 4291 `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). 4292 4293 Output Parameter: 4294 . M - pointer to place new matrix 4295 4296 Level: intermediate 4297 4298 Notes: 4299 `MatConvert()` first creates a new matrix and then copies the data from 4300 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4301 entries of one matrix to another already existing matrix context. 4302 4303 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4304 the MPI communicator of the generated matrix is always the same as the communicator 4305 of the input matrix. 4306 4307 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4308 @*/ 4309 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4310 { 4311 PetscBool sametype, issame, flg; 4312 PetscBool3 issymmetric, ishermitian; 4313 char convname[256], mtype[256]; 4314 Mat B; 4315 4316 PetscFunctionBegin; 4317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4318 PetscValidType(mat, 1); 4319 PetscAssertPointer(M, 4); 4320 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4321 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4322 MatCheckPreallocated(mat, 1); 4323 4324 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4325 if (flg) newtype = mtype; 4326 4327 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4328 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4329 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4330 if (reuse == MAT_REUSE_MATRIX) { 4331 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4332 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4333 } 4334 4335 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4336 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4337 PetscFunctionReturn(PETSC_SUCCESS); 4338 } 4339 4340 /* Cache Mat options because some converters use MatHeaderReplace */ 4341 issymmetric = mat->symmetric; 4342 ishermitian = mat->hermitian; 4343 4344 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4345 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4346 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4347 } else { 4348 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4349 const char *prefix[3] = {"seq", "mpi", ""}; 4350 PetscInt i; 4351 /* 4352 Order of precedence: 4353 0) See if newtype is a superclass of the current matrix. 4354 1) See if a specialized converter is known to the current matrix. 4355 2) See if a specialized converter is known to the desired matrix class. 4356 3) See if a good general converter is registered for the desired class 4357 (as of 6/27/03 only MATMPIADJ falls into this category). 4358 4) See if a good general converter is known for the current matrix. 4359 5) Use a really basic converter. 4360 */ 4361 4362 /* 0) See if newtype is a superclass of the current matrix. 4363 i.e mat is mpiaij and newtype is aij */ 4364 for (i = 0; i < 2; i++) { 4365 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4367 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4368 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4369 if (flg) { 4370 if (reuse == MAT_INPLACE_MATRIX) { 4371 PetscCall(PetscInfo(mat, "Early return\n")); 4372 PetscFunctionReturn(PETSC_SUCCESS); 4373 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4374 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4375 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4376 PetscFunctionReturn(PETSC_SUCCESS); 4377 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4378 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4379 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4380 PetscFunctionReturn(PETSC_SUCCESS); 4381 } 4382 } 4383 } 4384 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4385 for (i = 0; i < 3; i++) { 4386 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4387 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4388 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4389 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4390 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4391 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4392 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4393 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4394 if (conv) goto foundconv; 4395 } 4396 4397 /* 2) See if a specialized converter is known to the desired matrix class. */ 4398 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4399 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4400 PetscCall(MatSetType(B, newtype)); 4401 for (i = 0; i < 3; i++) { 4402 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4403 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4404 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4405 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4406 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4407 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4408 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4409 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4410 if (conv) { 4411 PetscCall(MatDestroy(&B)); 4412 goto foundconv; 4413 } 4414 } 4415 4416 /* 3) See if a good general converter is registered for the desired class */ 4417 conv = B->ops->convertfrom; 4418 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4419 PetscCall(MatDestroy(&B)); 4420 if (conv) goto foundconv; 4421 4422 /* 4) See if a good general converter is known for the current matrix */ 4423 if (mat->ops->convert) conv = mat->ops->convert; 4424 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4425 if (conv) goto foundconv; 4426 4427 /* 5) Use a really basic converter. */ 4428 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4429 conv = MatConvert_Basic; 4430 4431 foundconv: 4432 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4433 PetscCall((*conv)(mat, newtype, reuse, M)); 4434 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4435 /* the block sizes must be same if the mappings are copied over */ 4436 (*M)->rmap->bs = mat->rmap->bs; 4437 (*M)->cmap->bs = mat->cmap->bs; 4438 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4439 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4440 (*M)->rmap->mapping = mat->rmap->mapping; 4441 (*M)->cmap->mapping = mat->cmap->mapping; 4442 } 4443 (*M)->stencil.dim = mat->stencil.dim; 4444 (*M)->stencil.noc = mat->stencil.noc; 4445 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4446 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4447 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4448 } 4449 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4450 } 4451 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4452 4453 /* Copy Mat options */ 4454 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4455 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4456 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4457 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4458 PetscFunctionReturn(PETSC_SUCCESS); 4459 } 4460 4461 /*@C 4462 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4463 4464 Not Collective 4465 4466 Input Parameter: 4467 . mat - the matrix, must be a factored matrix 4468 4469 Output Parameter: 4470 . type - the string name of the package (do not free this string) 4471 4472 Level: intermediate 4473 4474 Fortran Note: 4475 Pass in an empty string that is long enough and the package name will be copied into it. 4476 4477 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4478 @*/ 4479 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4480 { 4481 PetscErrorCode (*conv)(Mat, MatSolverType *); 4482 4483 PetscFunctionBegin; 4484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4485 PetscValidType(mat, 1); 4486 PetscAssertPointer(type, 2); 4487 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4488 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4489 if (conv) PetscCall((*conv)(mat, type)); 4490 else *type = MATSOLVERPETSC; 4491 PetscFunctionReturn(PETSC_SUCCESS); 4492 } 4493 4494 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4495 struct _MatSolverTypeForSpecifcType { 4496 MatType mtype; 4497 /* no entry for MAT_FACTOR_NONE */ 4498 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4499 MatSolverTypeForSpecifcType next; 4500 }; 4501 4502 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4503 struct _MatSolverTypeHolder { 4504 char *name; 4505 MatSolverTypeForSpecifcType handlers; 4506 MatSolverTypeHolder next; 4507 }; 4508 4509 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4510 4511 /*@C 4512 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4513 4514 Input Parameters: 4515 + package - name of the package, for example petsc or superlu 4516 . mtype - the matrix type that works with this package 4517 . ftype - the type of factorization supported by the package 4518 - createfactor - routine that will create the factored matrix ready to be used 4519 4520 Level: developer 4521 4522 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4523 `MatGetFactor()` 4524 @*/ 4525 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4526 { 4527 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4528 PetscBool flg; 4529 MatSolverTypeForSpecifcType inext, iprev = NULL; 4530 4531 PetscFunctionBegin; 4532 PetscCall(MatInitializePackage()); 4533 if (!next) { 4534 PetscCall(PetscNew(&MatSolverTypeHolders)); 4535 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4536 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4537 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4538 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4539 PetscFunctionReturn(PETSC_SUCCESS); 4540 } 4541 while (next) { 4542 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4543 if (flg) { 4544 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4545 inext = next->handlers; 4546 while (inext) { 4547 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4548 if (flg) { 4549 inext->createfactor[(int)ftype - 1] = createfactor; 4550 PetscFunctionReturn(PETSC_SUCCESS); 4551 } 4552 iprev = inext; 4553 inext = inext->next; 4554 } 4555 PetscCall(PetscNew(&iprev->next)); 4556 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4557 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4558 PetscFunctionReturn(PETSC_SUCCESS); 4559 } 4560 prev = next; 4561 next = next->next; 4562 } 4563 PetscCall(PetscNew(&prev->next)); 4564 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4565 PetscCall(PetscNew(&prev->next->handlers)); 4566 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4567 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4568 PetscFunctionReturn(PETSC_SUCCESS); 4569 } 4570 4571 /*@C 4572 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4573 4574 Input Parameters: 4575 + 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 4576 . ftype - the type of factorization supported by the type 4577 - mtype - the matrix type that works with this type 4578 4579 Output Parameters: 4580 + foundtype - `PETSC_TRUE` if the type was registered 4581 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4582 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4583 4584 Calling sequence of `createfactor`: 4585 + A - the matrix providing the factor matrix 4586 . mtype - the `MatType` of the factor requested 4587 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4588 4589 Level: developer 4590 4591 Note: 4592 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4593 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4594 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4595 4596 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4597 `MatInitializePackage()` 4598 @*/ 4599 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4600 { 4601 MatSolverTypeHolder next = MatSolverTypeHolders; 4602 PetscBool flg; 4603 MatSolverTypeForSpecifcType inext; 4604 4605 PetscFunctionBegin; 4606 if (foundtype) *foundtype = PETSC_FALSE; 4607 if (foundmtype) *foundmtype = PETSC_FALSE; 4608 if (createfactor) *createfactor = NULL; 4609 4610 if (type) { 4611 while (next) { 4612 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4613 if (flg) { 4614 if (foundtype) *foundtype = PETSC_TRUE; 4615 inext = next->handlers; 4616 while (inext) { 4617 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4618 if (flg) { 4619 if (foundmtype) *foundmtype = PETSC_TRUE; 4620 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4621 PetscFunctionReturn(PETSC_SUCCESS); 4622 } 4623 inext = inext->next; 4624 } 4625 } 4626 next = next->next; 4627 } 4628 } else { 4629 while (next) { 4630 inext = next->handlers; 4631 while (inext) { 4632 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4633 if (flg && inext->createfactor[(int)ftype - 1]) { 4634 if (foundtype) *foundtype = PETSC_TRUE; 4635 if (foundmtype) *foundmtype = PETSC_TRUE; 4636 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4637 PetscFunctionReturn(PETSC_SUCCESS); 4638 } 4639 inext = inext->next; 4640 } 4641 next = next->next; 4642 } 4643 /* try with base classes inext->mtype */ 4644 next = MatSolverTypeHolders; 4645 while (next) { 4646 inext = next->handlers; 4647 while (inext) { 4648 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4649 if (flg && inext->createfactor[(int)ftype - 1]) { 4650 if (foundtype) *foundtype = PETSC_TRUE; 4651 if (foundmtype) *foundmtype = PETSC_TRUE; 4652 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4653 PetscFunctionReturn(PETSC_SUCCESS); 4654 } 4655 inext = inext->next; 4656 } 4657 next = next->next; 4658 } 4659 } 4660 PetscFunctionReturn(PETSC_SUCCESS); 4661 } 4662 4663 PetscErrorCode MatSolverTypeDestroy(void) 4664 { 4665 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4666 MatSolverTypeForSpecifcType inext, iprev; 4667 4668 PetscFunctionBegin; 4669 while (next) { 4670 PetscCall(PetscFree(next->name)); 4671 inext = next->handlers; 4672 while (inext) { 4673 PetscCall(PetscFree(inext->mtype)); 4674 iprev = inext; 4675 inext = inext->next; 4676 PetscCall(PetscFree(iprev)); 4677 } 4678 prev = next; 4679 next = next->next; 4680 PetscCall(PetscFree(prev)); 4681 } 4682 MatSolverTypeHolders = NULL; 4683 PetscFunctionReturn(PETSC_SUCCESS); 4684 } 4685 4686 /*@C 4687 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4688 4689 Logically Collective 4690 4691 Input Parameter: 4692 . mat - the matrix 4693 4694 Output Parameter: 4695 . flg - `PETSC_TRUE` if uses the ordering 4696 4697 Level: developer 4698 4699 Note: 4700 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4701 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4702 4703 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4704 @*/ 4705 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4706 { 4707 PetscFunctionBegin; 4708 *flg = mat->canuseordering; 4709 PetscFunctionReturn(PETSC_SUCCESS); 4710 } 4711 4712 /*@C 4713 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4714 4715 Logically Collective 4716 4717 Input Parameters: 4718 + mat - the matrix obtained with `MatGetFactor()` 4719 - ftype - the factorization type to be used 4720 4721 Output Parameter: 4722 . otype - the preferred ordering type 4723 4724 Level: developer 4725 4726 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4727 @*/ 4728 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4729 { 4730 PetscFunctionBegin; 4731 *otype = mat->preferredordering[ftype]; 4732 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4733 PetscFunctionReturn(PETSC_SUCCESS); 4734 } 4735 4736 /*@C 4737 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4738 4739 Collective 4740 4741 Input Parameters: 4742 + mat - the matrix 4743 . 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 4744 the other criteria is returned 4745 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4746 4747 Output Parameter: 4748 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4749 4750 Options Database Keys: 4751 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4752 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4753 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4754 4755 Level: intermediate 4756 4757 Notes: 4758 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4759 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4760 4761 Users usually access the factorization solvers via `KSP` 4762 4763 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4764 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 4765 4766 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4767 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4768 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4769 4770 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4771 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4772 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4773 4774 Developer Note: 4775 This should actually be called `MatCreateFactor()` since it creates a new factor object 4776 4777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4778 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4779 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4780 @*/ 4781 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4782 { 4783 PetscBool foundtype, foundmtype; 4784 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4785 4786 PetscFunctionBegin; 4787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4788 PetscValidType(mat, 1); 4789 4790 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4791 MatCheckPreallocated(mat, 1); 4792 4793 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4794 if (!foundtype) { 4795 if (type) { 4796 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], 4797 ((PetscObject)mat)->type_name, type); 4798 } else { 4799 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); 4800 } 4801 } 4802 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4803 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); 4804 4805 PetscCall((*conv)(mat, ftype, f)); 4806 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4807 PetscFunctionReturn(PETSC_SUCCESS); 4808 } 4809 4810 /*@C 4811 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4812 4813 Not Collective 4814 4815 Input Parameters: 4816 + mat - the matrix 4817 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4818 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4819 4820 Output Parameter: 4821 . flg - PETSC_TRUE if the factorization is available 4822 4823 Level: intermediate 4824 4825 Notes: 4826 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4827 such as pastix, superlu, mumps etc. 4828 4829 PETSc must have been ./configure to use the external solver, using the option --download-package 4830 4831 Developer Note: 4832 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4833 4834 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4835 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4836 @*/ 4837 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4838 { 4839 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4840 4841 PetscFunctionBegin; 4842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4843 PetscAssertPointer(flg, 4); 4844 4845 *flg = PETSC_FALSE; 4846 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4847 4848 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4849 MatCheckPreallocated(mat, 1); 4850 4851 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4852 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4853 PetscFunctionReturn(PETSC_SUCCESS); 4854 } 4855 4856 /*@ 4857 MatDuplicate - Duplicates a matrix including the non-zero structure. 4858 4859 Collective 4860 4861 Input Parameters: 4862 + mat - the matrix 4863 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4864 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4865 4866 Output Parameter: 4867 . M - pointer to place new matrix 4868 4869 Level: intermediate 4870 4871 Notes: 4872 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4873 4874 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4875 4876 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. 4877 4878 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4879 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4880 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4881 4882 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4883 @*/ 4884 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4885 { 4886 Mat B; 4887 VecType vtype; 4888 PetscInt i; 4889 PetscObject dm, container_h, container_d; 4890 void (*viewf)(void); 4891 4892 PetscFunctionBegin; 4893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4894 PetscValidType(mat, 1); 4895 PetscAssertPointer(M, 3); 4896 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4897 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4898 MatCheckPreallocated(mat, 1); 4899 4900 *M = NULL; 4901 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4902 PetscUseTypeMethod(mat, duplicate, op, M); 4903 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4904 B = *M; 4905 4906 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4907 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4908 PetscCall(MatGetVecType(mat, &vtype)); 4909 PetscCall(MatSetVecType(B, vtype)); 4910 4911 B->stencil.dim = mat->stencil.dim; 4912 B->stencil.noc = mat->stencil.noc; 4913 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4914 B->stencil.dims[i] = mat->stencil.dims[i]; 4915 B->stencil.starts[i] = mat->stencil.starts[i]; 4916 } 4917 4918 B->nooffproczerorows = mat->nooffproczerorows; 4919 B->nooffprocentries = mat->nooffprocentries; 4920 4921 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4922 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4923 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4924 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4925 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4926 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4927 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4928 PetscFunctionReturn(PETSC_SUCCESS); 4929 } 4930 4931 /*@ 4932 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4933 4934 Logically Collective 4935 4936 Input Parameter: 4937 . mat - the matrix 4938 4939 Output Parameter: 4940 . v - the diagonal of the matrix 4941 4942 Level: intermediate 4943 4944 Note: 4945 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4946 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4947 is larger than `ndiag`, the values of the remaining entries are unspecified. 4948 4949 Currently only correct in parallel for square matrices. 4950 4951 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4952 @*/ 4953 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4954 { 4955 PetscFunctionBegin; 4956 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4957 PetscValidType(mat, 1); 4958 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4959 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4960 MatCheckPreallocated(mat, 1); 4961 if (PetscDefined(USE_DEBUG)) { 4962 PetscInt nv, row, col, ndiag; 4963 4964 PetscCall(VecGetLocalSize(v, &nv)); 4965 PetscCall(MatGetLocalSize(mat, &row, &col)); 4966 ndiag = PetscMin(row, col); 4967 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); 4968 } 4969 4970 PetscUseTypeMethod(mat, getdiagonal, v); 4971 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4972 PetscFunctionReturn(PETSC_SUCCESS); 4973 } 4974 4975 /*@C 4976 MatGetRowMin - Gets the minimum value (of the real part) of each 4977 row of the matrix 4978 4979 Logically Collective 4980 4981 Input Parameter: 4982 . mat - the matrix 4983 4984 Output Parameters: 4985 + v - the vector for storing the maximums 4986 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 4987 4988 Level: intermediate 4989 4990 Note: 4991 The result of this call are the same as if one converted the matrix to dense format 4992 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4993 4994 This code is only implemented for a couple of matrix formats. 4995 4996 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4997 `MatGetRowMax()` 4998 @*/ 4999 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5000 { 5001 PetscFunctionBegin; 5002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5003 PetscValidType(mat, 1); 5004 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5005 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5006 5007 if (!mat->cmap->N) { 5008 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5009 if (idx) { 5010 PetscInt i, m = mat->rmap->n; 5011 for (i = 0; i < m; i++) idx[i] = -1; 5012 } 5013 } else { 5014 MatCheckPreallocated(mat, 1); 5015 } 5016 PetscUseTypeMethod(mat, getrowmin, v, idx); 5017 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5018 PetscFunctionReturn(PETSC_SUCCESS); 5019 } 5020 5021 /*@C 5022 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5023 row of the matrix 5024 5025 Logically Collective 5026 5027 Input Parameter: 5028 . mat - the matrix 5029 5030 Output Parameters: 5031 + v - the vector for storing the minimums 5032 - idx - the indices of the column found for each row (or `NULL` if not needed) 5033 5034 Level: intermediate 5035 5036 Notes: 5037 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5038 row is 0 (the first column). 5039 5040 This code is only implemented for a couple of matrix formats. 5041 5042 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5043 @*/ 5044 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5045 { 5046 PetscFunctionBegin; 5047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5048 PetscValidType(mat, 1); 5049 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5051 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5052 5053 if (!mat->cmap->N) { 5054 PetscCall(VecSet(v, 0.0)); 5055 if (idx) { 5056 PetscInt i, m = mat->rmap->n; 5057 for (i = 0; i < m; i++) idx[i] = -1; 5058 } 5059 } else { 5060 MatCheckPreallocated(mat, 1); 5061 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5062 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5063 } 5064 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5065 PetscFunctionReturn(PETSC_SUCCESS); 5066 } 5067 5068 /*@C 5069 MatGetRowMax - Gets the maximum value (of the real part) of each 5070 row of the matrix 5071 5072 Logically Collective 5073 5074 Input Parameter: 5075 . mat - the matrix 5076 5077 Output Parameters: 5078 + v - the vector for storing the maximums 5079 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5080 5081 Level: intermediate 5082 5083 Notes: 5084 The result of this call are the same as if one converted the matrix to dense format 5085 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5086 5087 This code is only implemented for a couple of matrix formats. 5088 5089 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5090 @*/ 5091 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5092 { 5093 PetscFunctionBegin; 5094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5095 PetscValidType(mat, 1); 5096 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5097 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5098 5099 if (!mat->cmap->N) { 5100 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5101 if (idx) { 5102 PetscInt i, m = mat->rmap->n; 5103 for (i = 0; i < m; i++) idx[i] = -1; 5104 } 5105 } else { 5106 MatCheckPreallocated(mat, 1); 5107 PetscUseTypeMethod(mat, getrowmax, v, idx); 5108 } 5109 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5110 PetscFunctionReturn(PETSC_SUCCESS); 5111 } 5112 5113 /*@C 5114 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5115 row of the matrix 5116 5117 Logically Collective 5118 5119 Input Parameter: 5120 . mat - the matrix 5121 5122 Output Parameters: 5123 + v - the vector for storing the maximums 5124 - idx - the indices of the column found for each row (or `NULL` if not needed) 5125 5126 Level: intermediate 5127 5128 Notes: 5129 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5130 row is 0 (the first column). 5131 5132 This code is only implemented for a couple of matrix formats. 5133 5134 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5135 @*/ 5136 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5137 { 5138 PetscFunctionBegin; 5139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5140 PetscValidType(mat, 1); 5141 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5143 5144 if (!mat->cmap->N) { 5145 PetscCall(VecSet(v, 0.0)); 5146 if (idx) { 5147 PetscInt i, m = mat->rmap->n; 5148 for (i = 0; i < m; i++) idx[i] = -1; 5149 } 5150 } else { 5151 MatCheckPreallocated(mat, 1); 5152 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5153 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5154 } 5155 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5156 PetscFunctionReturn(PETSC_SUCCESS); 5157 } 5158 5159 /*@ 5160 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5161 5162 Logically Collective 5163 5164 Input Parameter: 5165 . mat - the matrix 5166 5167 Output Parameter: 5168 . v - the vector for storing the sum 5169 5170 Level: intermediate 5171 5172 This code is only implemented for a couple of matrix formats. 5173 5174 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5175 @*/ 5176 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5177 { 5178 PetscFunctionBegin; 5179 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5180 PetscValidType(mat, 1); 5181 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5182 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5183 5184 if (!mat->cmap->N) { 5185 PetscCall(VecSet(v, 0.0)); 5186 } else { 5187 MatCheckPreallocated(mat, 1); 5188 PetscUseTypeMethod(mat, getrowsumabs, v); 5189 } 5190 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5191 PetscFunctionReturn(PETSC_SUCCESS); 5192 } 5193 5194 /*@ 5195 MatGetRowSum - Gets the sum of each row of the matrix 5196 5197 Logically or Neighborhood Collective 5198 5199 Input Parameter: 5200 . mat - the matrix 5201 5202 Output Parameter: 5203 . v - the vector for storing the sum of rows 5204 5205 Level: intermediate 5206 5207 Note: 5208 This code is slow since it is not currently specialized for different formats 5209 5210 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5211 @*/ 5212 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5213 { 5214 Vec ones; 5215 5216 PetscFunctionBegin; 5217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5218 PetscValidType(mat, 1); 5219 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5220 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5221 MatCheckPreallocated(mat, 1); 5222 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5223 PetscCall(VecSet(ones, 1.)); 5224 PetscCall(MatMult(mat, ones, v)); 5225 PetscCall(VecDestroy(&ones)); 5226 PetscFunctionReturn(PETSC_SUCCESS); 5227 } 5228 5229 /*@ 5230 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5231 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5232 5233 Collective 5234 5235 Input Parameter: 5236 . mat - the matrix to provide the transpose 5237 5238 Output Parameter: 5239 . 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 5240 5241 Level: advanced 5242 5243 Note: 5244 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 5245 routine allows bypassing that call. 5246 5247 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5248 @*/ 5249 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5250 { 5251 PetscContainer rB = NULL; 5252 MatParentState *rb = NULL; 5253 5254 PetscFunctionBegin; 5255 PetscCall(PetscNew(&rb)); 5256 rb->id = ((PetscObject)mat)->id; 5257 rb->state = 0; 5258 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5259 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5260 PetscCall(PetscContainerSetPointer(rB, rb)); 5261 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5262 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5263 PetscCall(PetscObjectDereference((PetscObject)rB)); 5264 PetscFunctionReturn(PETSC_SUCCESS); 5265 } 5266 5267 /*@ 5268 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5269 5270 Collective 5271 5272 Input Parameters: 5273 + mat - the matrix to transpose 5274 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5275 5276 Output Parameter: 5277 . B - the transpose 5278 5279 Level: intermediate 5280 5281 Notes: 5282 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5283 5284 `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 5285 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5286 5287 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. 5288 5289 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5290 5291 If mat is unchanged from the last call this function returns immediately without recomputing the result 5292 5293 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5294 5295 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5296 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5297 @*/ 5298 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5299 { 5300 PetscContainer rB = NULL; 5301 MatParentState *rb = NULL; 5302 5303 PetscFunctionBegin; 5304 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5305 PetscValidType(mat, 1); 5306 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5307 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5308 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5309 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5310 MatCheckPreallocated(mat, 1); 5311 if (reuse == MAT_REUSE_MATRIX) { 5312 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5313 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5314 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5315 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5316 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5317 } 5318 5319 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5320 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5321 PetscUseTypeMethod(mat, transpose, reuse, B); 5322 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5323 } 5324 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5325 5326 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5327 if (reuse != MAT_INPLACE_MATRIX) { 5328 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5329 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5330 rb->state = ((PetscObject)mat)->state; 5331 rb->nonzerostate = mat->nonzerostate; 5332 } 5333 PetscFunctionReturn(PETSC_SUCCESS); 5334 } 5335 5336 /*@ 5337 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5338 5339 Collective 5340 5341 Input Parameter: 5342 . A - the matrix to transpose 5343 5344 Output Parameter: 5345 . 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 5346 numerical portion. 5347 5348 Level: intermediate 5349 5350 Note: 5351 This is not supported for many matrix types, use `MatTranspose()` in those cases 5352 5353 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5354 @*/ 5355 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5356 { 5357 PetscFunctionBegin; 5358 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5359 PetscValidType(A, 1); 5360 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5361 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5362 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5363 PetscUseTypeMethod(A, transposesymbolic, B); 5364 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5365 5366 PetscCall(MatTransposeSetPrecursor(A, *B)); 5367 PetscFunctionReturn(PETSC_SUCCESS); 5368 } 5369 5370 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5371 { 5372 PetscContainer rB; 5373 MatParentState *rb; 5374 5375 PetscFunctionBegin; 5376 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5377 PetscValidType(A, 1); 5378 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5379 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5380 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5381 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5382 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5383 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5384 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5385 PetscFunctionReturn(PETSC_SUCCESS); 5386 } 5387 5388 /*@ 5389 MatIsTranspose - Test whether a matrix is another one's transpose, 5390 or its own, in which case it tests symmetry. 5391 5392 Collective 5393 5394 Input Parameters: 5395 + A - the matrix to test 5396 . B - the matrix to test against, this can equal the first parameter 5397 - tol - tolerance, differences between entries smaller than this are counted as zero 5398 5399 Output Parameter: 5400 . flg - the result 5401 5402 Level: intermediate 5403 5404 Notes: 5405 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5406 test involves parallel copies of the block off-diagonal parts of the matrix. 5407 5408 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5409 @*/ 5410 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5411 { 5412 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5413 5414 PetscFunctionBegin; 5415 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5416 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5417 PetscAssertPointer(flg, 4); 5418 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5419 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5420 *flg = PETSC_FALSE; 5421 if (f && g) { 5422 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5423 PetscCall((*f)(A, B, tol, flg)); 5424 } else { 5425 MatType mattype; 5426 5427 PetscCall(MatGetType(f ? B : A, &mattype)); 5428 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5429 } 5430 PetscFunctionReturn(PETSC_SUCCESS); 5431 } 5432 5433 /*@ 5434 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5435 5436 Collective 5437 5438 Input Parameters: 5439 + mat - the matrix to transpose and complex conjugate 5440 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5441 5442 Output Parameter: 5443 . B - the Hermitian transpose 5444 5445 Level: intermediate 5446 5447 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5448 @*/ 5449 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5450 { 5451 PetscFunctionBegin; 5452 PetscCall(MatTranspose(mat, reuse, B)); 5453 #if defined(PETSC_USE_COMPLEX) 5454 PetscCall(MatConjugate(*B)); 5455 #endif 5456 PetscFunctionReturn(PETSC_SUCCESS); 5457 } 5458 5459 /*@ 5460 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5461 5462 Collective 5463 5464 Input Parameters: 5465 + A - the matrix to test 5466 . B - the matrix to test against, this can equal the first parameter 5467 - tol - tolerance, differences between entries smaller than this are counted as zero 5468 5469 Output Parameter: 5470 . flg - the result 5471 5472 Level: intermediate 5473 5474 Notes: 5475 Only available for `MATAIJ` matrices. 5476 5477 The sequential algorithm 5478 has a running time of the order of the number of nonzeros; the parallel 5479 test involves parallel copies of the block off-diagonal parts of the matrix. 5480 5481 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5482 @*/ 5483 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5484 { 5485 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5486 5487 PetscFunctionBegin; 5488 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5489 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5490 PetscAssertPointer(flg, 4); 5491 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5492 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5493 if (f && g) { 5494 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5495 PetscCall((*f)(A, B, tol, flg)); 5496 } 5497 PetscFunctionReturn(PETSC_SUCCESS); 5498 } 5499 5500 /*@ 5501 MatPermute - Creates a new matrix with rows and columns permuted from the 5502 original. 5503 5504 Collective 5505 5506 Input Parameters: 5507 + mat - the matrix to permute 5508 . row - row permutation, each processor supplies only the permutation for its rows 5509 - col - column permutation, each processor supplies only the permutation for its columns 5510 5511 Output Parameter: 5512 . B - the permuted matrix 5513 5514 Level: advanced 5515 5516 Note: 5517 The index sets map from row/col of permuted matrix to row/col of original matrix. 5518 The index sets should be on the same communicator as mat and have the same local sizes. 5519 5520 Developer Note: 5521 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5522 exploit the fact that row and col are permutations, consider implementing the 5523 more general `MatCreateSubMatrix()` instead. 5524 5525 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5526 @*/ 5527 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5528 { 5529 PetscFunctionBegin; 5530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5531 PetscValidType(mat, 1); 5532 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5533 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5534 PetscAssertPointer(B, 4); 5535 PetscCheckSameComm(mat, 1, row, 2); 5536 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5537 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5538 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5539 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5540 MatCheckPreallocated(mat, 1); 5541 5542 if (mat->ops->permute) { 5543 PetscUseTypeMethod(mat, permute, row, col, B); 5544 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5545 } else { 5546 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5547 } 5548 PetscFunctionReturn(PETSC_SUCCESS); 5549 } 5550 5551 /*@ 5552 MatEqual - Compares two matrices. 5553 5554 Collective 5555 5556 Input Parameters: 5557 + A - the first matrix 5558 - B - the second matrix 5559 5560 Output Parameter: 5561 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5562 5563 Level: intermediate 5564 5565 .seealso: [](ch_matrices), `Mat` 5566 @*/ 5567 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5568 { 5569 PetscFunctionBegin; 5570 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5571 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5572 PetscValidType(A, 1); 5573 PetscValidType(B, 2); 5574 PetscAssertPointer(flg, 3); 5575 PetscCheckSameComm(A, 1, B, 2); 5576 MatCheckPreallocated(A, 1); 5577 MatCheckPreallocated(B, 2); 5578 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5579 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5580 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, 5581 B->cmap->N); 5582 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5583 PetscUseTypeMethod(A, equal, B, flg); 5584 } else { 5585 PetscCall(MatMultEqual(A, B, 10, flg)); 5586 } 5587 PetscFunctionReturn(PETSC_SUCCESS); 5588 } 5589 5590 /*@ 5591 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5592 matrices that are stored as vectors. Either of the two scaling 5593 matrices can be `NULL`. 5594 5595 Collective 5596 5597 Input Parameters: 5598 + mat - the matrix to be scaled 5599 . l - the left scaling vector (or `NULL`) 5600 - r - the right scaling vector (or `NULL`) 5601 5602 Level: intermediate 5603 5604 Note: 5605 `MatDiagonalScale()` computes $A = LAR$, where 5606 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5607 The L scales the rows of the matrix, the R scales the columns of the matrix. 5608 5609 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5610 @*/ 5611 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5612 { 5613 PetscFunctionBegin; 5614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5615 PetscValidType(mat, 1); 5616 if (l) { 5617 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5618 PetscCheckSameComm(mat, 1, l, 2); 5619 } 5620 if (r) { 5621 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5622 PetscCheckSameComm(mat, 1, r, 3); 5623 } 5624 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5625 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5626 MatCheckPreallocated(mat, 1); 5627 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5628 5629 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5630 PetscUseTypeMethod(mat, diagonalscale, l, r); 5631 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5632 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5633 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5634 PetscFunctionReturn(PETSC_SUCCESS); 5635 } 5636 5637 /*@ 5638 MatScale - Scales all elements of a matrix by a given number. 5639 5640 Logically Collective 5641 5642 Input Parameters: 5643 + mat - the matrix to be scaled 5644 - a - the scaling value 5645 5646 Level: intermediate 5647 5648 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5649 @*/ 5650 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5651 { 5652 PetscFunctionBegin; 5653 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5654 PetscValidType(mat, 1); 5655 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5656 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5657 PetscValidLogicalCollectiveScalar(mat, a, 2); 5658 MatCheckPreallocated(mat, 1); 5659 5660 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5661 if (a != (PetscScalar)1.0) { 5662 PetscUseTypeMethod(mat, scale, a); 5663 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5664 } 5665 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5666 PetscFunctionReturn(PETSC_SUCCESS); 5667 } 5668 5669 /*@ 5670 MatNorm - Calculates various norms of a matrix. 5671 5672 Collective 5673 5674 Input Parameters: 5675 + mat - the matrix 5676 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5677 5678 Output Parameter: 5679 . nrm - the resulting norm 5680 5681 Level: intermediate 5682 5683 .seealso: [](ch_matrices), `Mat` 5684 @*/ 5685 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5686 { 5687 PetscFunctionBegin; 5688 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5689 PetscValidType(mat, 1); 5690 PetscAssertPointer(nrm, 3); 5691 5692 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5693 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5694 MatCheckPreallocated(mat, 1); 5695 5696 PetscUseTypeMethod(mat, norm, type, nrm); 5697 PetscFunctionReturn(PETSC_SUCCESS); 5698 } 5699 5700 /* 5701 This variable is used to prevent counting of MatAssemblyBegin() that 5702 are called from within a MatAssemblyEnd(). 5703 */ 5704 static PetscInt MatAssemblyEnd_InUse = 0; 5705 /*@ 5706 MatAssemblyBegin - Begins assembling the matrix. This routine should 5707 be called after completing all calls to `MatSetValues()`. 5708 5709 Collective 5710 5711 Input Parameters: 5712 + mat - the matrix 5713 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5714 5715 Level: beginner 5716 5717 Notes: 5718 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5719 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5720 5721 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5722 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5723 using the matrix. 5724 5725 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5726 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 5727 a global collective operation requiring all processes that share the matrix. 5728 5729 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5730 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5731 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5732 5733 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5734 @*/ 5735 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5736 { 5737 PetscFunctionBegin; 5738 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5739 PetscValidType(mat, 1); 5740 MatCheckPreallocated(mat, 1); 5741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5742 if (mat->assembled) { 5743 mat->was_assembled = PETSC_TRUE; 5744 mat->assembled = PETSC_FALSE; 5745 } 5746 5747 if (!MatAssemblyEnd_InUse) { 5748 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5749 PetscTryTypeMethod(mat, assemblybegin, type); 5750 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5751 } else PetscTryTypeMethod(mat, assemblybegin, type); 5752 PetscFunctionReturn(PETSC_SUCCESS); 5753 } 5754 5755 /*@ 5756 MatAssembled - Indicates if a matrix has been assembled and is ready for 5757 use; for example, in matrix-vector product. 5758 5759 Not Collective 5760 5761 Input Parameter: 5762 . mat - the matrix 5763 5764 Output Parameter: 5765 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5766 5767 Level: advanced 5768 5769 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5770 @*/ 5771 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5772 { 5773 PetscFunctionBegin; 5774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5775 PetscAssertPointer(assembled, 2); 5776 *assembled = mat->assembled; 5777 PetscFunctionReturn(PETSC_SUCCESS); 5778 } 5779 5780 /*@ 5781 MatAssemblyEnd - Completes assembling the matrix. This routine should 5782 be called after `MatAssemblyBegin()`. 5783 5784 Collective 5785 5786 Input Parameters: 5787 + mat - the matrix 5788 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5789 5790 Options Database Keys: 5791 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5792 . -mat_view ::ascii_info_detail - Prints more detailed info 5793 . -mat_view - Prints matrix in ASCII format 5794 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5795 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5796 . -display <name> - Sets display name (default is host) 5797 . -draw_pause <sec> - Sets number of seconds to pause after display 5798 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5799 . -viewer_socket_machine <machine> - Machine to use for socket 5800 . -viewer_socket_port <port> - Port number to use for socket 5801 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5802 5803 Level: beginner 5804 5805 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5806 @*/ 5807 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5808 { 5809 static PetscInt inassm = 0; 5810 PetscBool flg = PETSC_FALSE; 5811 5812 PetscFunctionBegin; 5813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5814 PetscValidType(mat, 1); 5815 5816 inassm++; 5817 MatAssemblyEnd_InUse++; 5818 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5819 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5820 PetscTryTypeMethod(mat, assemblyend, type); 5821 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5822 } else PetscTryTypeMethod(mat, assemblyend, type); 5823 5824 /* Flush assembly is not a true assembly */ 5825 if (type != MAT_FLUSH_ASSEMBLY) { 5826 if (mat->num_ass) { 5827 if (!mat->symmetry_eternal) { 5828 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5829 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5830 } 5831 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5832 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5833 } 5834 mat->num_ass++; 5835 mat->assembled = PETSC_TRUE; 5836 mat->ass_nonzerostate = mat->nonzerostate; 5837 } 5838 5839 mat->insertmode = NOT_SET_VALUES; 5840 MatAssemblyEnd_InUse--; 5841 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5842 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5843 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5844 5845 if (mat->checksymmetryonassembly) { 5846 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5847 if (flg) { 5848 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5849 } else { 5850 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5851 } 5852 } 5853 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5854 } 5855 inassm--; 5856 PetscFunctionReturn(PETSC_SUCCESS); 5857 } 5858 5859 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5860 /*@ 5861 MatSetOption - Sets a parameter option for a matrix. Some options 5862 may be specific to certain storage formats. Some options 5863 determine how values will be inserted (or added). Sorted, 5864 row-oriented input will generally assemble the fastest. The default 5865 is row-oriented. 5866 5867 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5868 5869 Input Parameters: 5870 + mat - the matrix 5871 . op - the option, one of those listed below (and possibly others), 5872 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5873 5874 Options Describing Matrix Structure: 5875 + `MAT_SPD` - symmetric positive definite 5876 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5877 . `MAT_HERMITIAN` - transpose is the complex conjugation 5878 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5879 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5880 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5881 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5882 5883 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5884 do not need to be computed (usually at a high cost) 5885 5886 Options For Use with `MatSetValues()`: 5887 Insert a logically dense subblock, which can be 5888 . `MAT_ROW_ORIENTED` - row-oriented (default) 5889 5890 These options reflect the data you pass in with `MatSetValues()`; it has 5891 nothing to do with how the data is stored internally in the matrix 5892 data structure. 5893 5894 When (re)assembling a matrix, we can restrict the input for 5895 efficiency/debugging purposes. These options include 5896 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5897 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5898 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5899 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5900 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5901 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5902 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5903 performance for very large process counts. 5904 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5905 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5906 functions, instead sending only neighbor messages. 5907 5908 Level: intermediate 5909 5910 Notes: 5911 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5912 5913 Some options are relevant only for particular matrix types and 5914 are thus ignored by others. Other options are not supported by 5915 certain matrix types and will generate an error message if set. 5916 5917 If using Fortran to compute a matrix, one may need to 5918 use the column-oriented option (or convert to the row-oriented 5919 format). 5920 5921 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5922 that would generate a new entry in the nonzero structure is instead 5923 ignored. Thus, if memory has not already been allocated for this particular 5924 data, then the insertion is ignored. For dense matrices, in which 5925 the entire array is allocated, no entries are ever ignored. 5926 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5927 5928 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5929 that would generate a new entry in the nonzero structure instead produces 5930 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 5931 5932 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5933 that would generate a new entry that has not been preallocated will 5934 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5935 only.) This is a useful flag when debugging matrix memory preallocation. 5936 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5937 5938 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5939 other processors should be dropped, rather than stashed. 5940 This is useful if you know that the "owning" processor is also 5941 always generating the correct matrix entries, so that PETSc need 5942 not transfer duplicate entries generated on another processor. 5943 5944 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5945 searches during matrix assembly. When this flag is set, the hash table 5946 is created during the first matrix assembly. This hash table is 5947 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5948 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5949 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5950 supported by `MATMPIBAIJ` format only. 5951 5952 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5953 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 5954 5955 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5956 a zero location in the matrix 5957 5958 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5959 5960 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5961 zero row routines and thus improves performance for very large process counts. 5962 5963 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5964 part of the matrix (since they should match the upper triangular part). 5965 5966 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5967 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 5968 with finite difference schemes with non-periodic boundary conditions. 5969 5970 Developer Note: 5971 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5972 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 5973 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5974 not changed. 5975 5976 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5977 @*/ 5978 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5979 { 5980 PetscFunctionBegin; 5981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5982 if (op > 0) { 5983 PetscValidLogicalCollectiveEnum(mat, op, 2); 5984 PetscValidLogicalCollectiveBool(mat, flg, 3); 5985 } 5986 5987 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); 5988 5989 switch (op) { 5990 case MAT_FORCE_DIAGONAL_ENTRIES: 5991 mat->force_diagonals = flg; 5992 PetscFunctionReturn(PETSC_SUCCESS); 5993 case MAT_NO_OFF_PROC_ENTRIES: 5994 mat->nooffprocentries = flg; 5995 PetscFunctionReturn(PETSC_SUCCESS); 5996 case MAT_SUBSET_OFF_PROC_ENTRIES: 5997 mat->assembly_subset = flg; 5998 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5999 #if !defined(PETSC_HAVE_MPIUNI) 6000 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6001 #endif 6002 mat->stash.first_assembly_done = PETSC_FALSE; 6003 } 6004 PetscFunctionReturn(PETSC_SUCCESS); 6005 case MAT_NO_OFF_PROC_ZERO_ROWS: 6006 mat->nooffproczerorows = flg; 6007 PetscFunctionReturn(PETSC_SUCCESS); 6008 case MAT_SPD: 6009 if (flg) { 6010 mat->spd = PETSC_BOOL3_TRUE; 6011 mat->symmetric = PETSC_BOOL3_TRUE; 6012 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6013 } else { 6014 mat->spd = PETSC_BOOL3_FALSE; 6015 } 6016 break; 6017 case MAT_SYMMETRIC: 6018 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6019 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6020 #if !defined(PETSC_USE_COMPLEX) 6021 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6022 #endif 6023 break; 6024 case MAT_HERMITIAN: 6025 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6026 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6027 #if !defined(PETSC_USE_COMPLEX) 6028 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6029 #endif 6030 break; 6031 case MAT_STRUCTURALLY_SYMMETRIC: 6032 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6033 break; 6034 case MAT_SYMMETRY_ETERNAL: 6035 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"); 6036 mat->symmetry_eternal = flg; 6037 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6038 break; 6039 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6040 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"); 6041 mat->structural_symmetry_eternal = flg; 6042 break; 6043 case MAT_SPD_ETERNAL: 6044 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"); 6045 mat->spd_eternal = flg; 6046 if (flg) { 6047 mat->structural_symmetry_eternal = PETSC_TRUE; 6048 mat->symmetry_eternal = PETSC_TRUE; 6049 } 6050 break; 6051 case MAT_STRUCTURE_ONLY: 6052 mat->structure_only = flg; 6053 break; 6054 case MAT_SORTED_FULL: 6055 mat->sortedfull = flg; 6056 break; 6057 default: 6058 break; 6059 } 6060 PetscTryTypeMethod(mat, setoption, op, flg); 6061 PetscFunctionReturn(PETSC_SUCCESS); 6062 } 6063 6064 /*@ 6065 MatGetOption - Gets a parameter option that has been set for a matrix. 6066 6067 Logically Collective 6068 6069 Input Parameters: 6070 + mat - the matrix 6071 - op - the option, this only responds to certain options, check the code for which ones 6072 6073 Output Parameter: 6074 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6075 6076 Level: intermediate 6077 6078 Notes: 6079 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6080 6081 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6082 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6083 6084 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6085 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6086 @*/ 6087 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6088 { 6089 PetscFunctionBegin; 6090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6091 PetscValidType(mat, 1); 6092 6093 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); 6094 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()"); 6095 6096 switch (op) { 6097 case MAT_NO_OFF_PROC_ENTRIES: 6098 *flg = mat->nooffprocentries; 6099 break; 6100 case MAT_NO_OFF_PROC_ZERO_ROWS: 6101 *flg = mat->nooffproczerorows; 6102 break; 6103 case MAT_SYMMETRIC: 6104 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6105 break; 6106 case MAT_HERMITIAN: 6107 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6108 break; 6109 case MAT_STRUCTURALLY_SYMMETRIC: 6110 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6111 break; 6112 case MAT_SPD: 6113 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6114 break; 6115 case MAT_SYMMETRY_ETERNAL: 6116 *flg = mat->symmetry_eternal; 6117 break; 6118 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6119 *flg = mat->symmetry_eternal; 6120 break; 6121 default: 6122 break; 6123 } 6124 PetscFunctionReturn(PETSC_SUCCESS); 6125 } 6126 6127 /*@ 6128 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6129 this routine retains the old nonzero structure. 6130 6131 Logically Collective 6132 6133 Input Parameter: 6134 . mat - the matrix 6135 6136 Level: intermediate 6137 6138 Note: 6139 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. 6140 See the Performance chapter of the users manual for information on preallocating matrices. 6141 6142 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6143 @*/ 6144 PetscErrorCode MatZeroEntries(Mat mat) 6145 { 6146 PetscFunctionBegin; 6147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6148 PetscValidType(mat, 1); 6149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6150 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"); 6151 MatCheckPreallocated(mat, 1); 6152 6153 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6154 PetscUseTypeMethod(mat, zeroentries); 6155 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6156 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6157 PetscFunctionReturn(PETSC_SUCCESS); 6158 } 6159 6160 /*@ 6161 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6162 of a set of rows and columns of a matrix. 6163 6164 Collective 6165 6166 Input Parameters: 6167 + mat - the matrix 6168 . numRows - the number of rows/columns to zero 6169 . rows - the global row indices 6170 . diag - value put in the diagonal of the eliminated rows 6171 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6172 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6173 6174 Level: intermediate 6175 6176 Notes: 6177 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6178 6179 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6180 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 6181 6182 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6183 Krylov method to take advantage of the known solution on the zeroed rows. 6184 6185 For the parallel case, all processes that share the matrix (i.e., 6186 those in the communicator used for matrix creation) MUST call this 6187 routine, regardless of whether any rows being zeroed are owned by 6188 them. 6189 6190 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6191 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 6192 missing. 6193 6194 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6195 list only rows local to itself). 6196 6197 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6198 6199 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6200 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6201 @*/ 6202 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6203 { 6204 PetscFunctionBegin; 6205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6206 PetscValidType(mat, 1); 6207 if (numRows) PetscAssertPointer(rows, 3); 6208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6209 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6210 MatCheckPreallocated(mat, 1); 6211 6212 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6213 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6214 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6215 PetscFunctionReturn(PETSC_SUCCESS); 6216 } 6217 6218 /*@ 6219 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6220 of a set of rows and columns of a matrix. 6221 6222 Collective 6223 6224 Input Parameters: 6225 + mat - the matrix 6226 . is - the rows to zero 6227 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6228 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6229 - b - optional vector of right-hand side, that will be adjusted by provided solution 6230 6231 Level: intermediate 6232 6233 Note: 6234 See `MatZeroRowsColumns()` for details on how this routine operates. 6235 6236 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6237 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6238 @*/ 6239 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6240 { 6241 PetscInt numRows; 6242 const PetscInt *rows; 6243 6244 PetscFunctionBegin; 6245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6246 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6247 PetscValidType(mat, 1); 6248 PetscValidType(is, 2); 6249 PetscCall(ISGetLocalSize(is, &numRows)); 6250 PetscCall(ISGetIndices(is, &rows)); 6251 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6252 PetscCall(ISRestoreIndices(is, &rows)); 6253 PetscFunctionReturn(PETSC_SUCCESS); 6254 } 6255 6256 /*@ 6257 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6258 of a set of rows of a matrix. 6259 6260 Collective 6261 6262 Input Parameters: 6263 + mat - the matrix 6264 . numRows - the number of rows to zero 6265 . rows - the global row indices 6266 . diag - value put in the diagonal of the zeroed rows 6267 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6268 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6269 6270 Level: intermediate 6271 6272 Notes: 6273 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6274 6275 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6276 6277 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6278 Krylov method to take advantage of the known solution on the zeroed rows. 6279 6280 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) 6281 from the matrix. 6282 6283 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6284 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 6285 formats this does not alter the nonzero structure. 6286 6287 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6288 of the matrix is not changed the values are 6289 merely zeroed. 6290 6291 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6292 formats can optionally remove the main diagonal entry from the 6293 nonzero structure as well, by passing 0.0 as the final argument). 6294 6295 For the parallel case, all processes that share the matrix (i.e., 6296 those in the communicator used for matrix creation) MUST call this 6297 routine, regardless of whether any rows being zeroed are owned by 6298 them. 6299 6300 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6301 list only rows local to itself). 6302 6303 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6304 owns that are to be zeroed. This saves a global synchronization in the implementation. 6305 6306 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6307 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6308 @*/ 6309 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6310 { 6311 PetscFunctionBegin; 6312 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6313 PetscValidType(mat, 1); 6314 if (numRows) PetscAssertPointer(rows, 3); 6315 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6316 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6317 MatCheckPreallocated(mat, 1); 6318 6319 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6320 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6321 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6322 PetscFunctionReturn(PETSC_SUCCESS); 6323 } 6324 6325 /*@ 6326 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6327 of a set of rows of a matrix. 6328 6329 Collective 6330 6331 Input Parameters: 6332 + mat - the matrix 6333 . is - index set of rows to remove (if `NULL` then no row is removed) 6334 . diag - value put in all diagonals of eliminated rows 6335 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6336 - b - optional vector of right-hand side, that will be adjusted by provided solution 6337 6338 Level: intermediate 6339 6340 Note: 6341 See `MatZeroRows()` for details on how this routine operates. 6342 6343 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6344 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6345 @*/ 6346 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6347 { 6348 PetscInt numRows = 0; 6349 const PetscInt *rows = NULL; 6350 6351 PetscFunctionBegin; 6352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6353 PetscValidType(mat, 1); 6354 if (is) { 6355 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6356 PetscCall(ISGetLocalSize(is, &numRows)); 6357 PetscCall(ISGetIndices(is, &rows)); 6358 } 6359 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6360 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6361 PetscFunctionReturn(PETSC_SUCCESS); 6362 } 6363 6364 /*@ 6365 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6366 of a set of rows of a matrix. These rows must be local to the process. 6367 6368 Collective 6369 6370 Input Parameters: 6371 + mat - the matrix 6372 . numRows - the number of rows to remove 6373 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6374 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6375 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6376 - b - optional vector of right-hand side, that will be adjusted by provided solution 6377 6378 Level: intermediate 6379 6380 Notes: 6381 See `MatZeroRows()` for details on how this routine operates. 6382 6383 The grid coordinates are across the entire grid, not just the local portion 6384 6385 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6386 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6387 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6388 `DM_BOUNDARY_PERIODIC` boundary type. 6389 6390 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 6391 a single value per point) you can skip filling those indices. 6392 6393 Fortran Note: 6394 `idxm` and `idxn` should be declared as 6395 $ MatStencil idxm(4, m) 6396 and the values inserted using 6397 .vb 6398 idxm(MatStencil_i, 1) = i 6399 idxm(MatStencil_j, 1) = j 6400 idxm(MatStencil_k, 1) = k 6401 idxm(MatStencil_c, 1) = c 6402 etc 6403 .ve 6404 6405 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6406 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6407 @*/ 6408 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6409 { 6410 PetscInt dim = mat->stencil.dim; 6411 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6412 PetscInt *dims = mat->stencil.dims + 1; 6413 PetscInt *starts = mat->stencil.starts; 6414 PetscInt *dxm = (PetscInt *)rows; 6415 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6416 6417 PetscFunctionBegin; 6418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6419 PetscValidType(mat, 1); 6420 if (numRows) PetscAssertPointer(rows, 3); 6421 6422 PetscCall(PetscMalloc1(numRows, &jdxm)); 6423 for (i = 0; i < numRows; ++i) { 6424 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6425 for (j = 0; j < 3 - sdim; ++j) dxm++; 6426 /* Local index in X dir */ 6427 tmp = *dxm++ - starts[0]; 6428 /* Loop over remaining dimensions */ 6429 for (j = 0; j < dim - 1; ++j) { 6430 /* If nonlocal, set index to be negative */ 6431 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6432 /* Update local index */ 6433 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6434 } 6435 /* Skip component slot if necessary */ 6436 if (mat->stencil.noc) dxm++; 6437 /* Local row number */ 6438 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6439 } 6440 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6441 PetscCall(PetscFree(jdxm)); 6442 PetscFunctionReturn(PETSC_SUCCESS); 6443 } 6444 6445 /*@ 6446 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6447 of a set of rows and columns of a matrix. 6448 6449 Collective 6450 6451 Input Parameters: 6452 + mat - the matrix 6453 . numRows - the number of rows/columns to remove 6454 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6455 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6456 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6457 - b - optional vector of right-hand side, that will be adjusted by provided solution 6458 6459 Level: intermediate 6460 6461 Notes: 6462 See `MatZeroRowsColumns()` for details on how this routine operates. 6463 6464 The grid coordinates are across the entire grid, not just the local portion 6465 6466 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6467 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6468 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6469 `DM_BOUNDARY_PERIODIC` boundary type. 6470 6471 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 6472 a single value per point) you can skip filling those indices. 6473 6474 Fortran Note: 6475 `idxm` and `idxn` should be declared as 6476 $ MatStencil idxm(4, m) 6477 and the values inserted using 6478 .vb 6479 idxm(MatStencil_i, 1) = i 6480 idxm(MatStencil_j, 1) = j 6481 idxm(MatStencil_k, 1) = k 6482 idxm(MatStencil_c, 1) = c 6483 etc 6484 .ve 6485 6486 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6487 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6488 @*/ 6489 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6490 { 6491 PetscInt dim = mat->stencil.dim; 6492 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6493 PetscInt *dims = mat->stencil.dims + 1; 6494 PetscInt *starts = mat->stencil.starts; 6495 PetscInt *dxm = (PetscInt *)rows; 6496 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6497 6498 PetscFunctionBegin; 6499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6500 PetscValidType(mat, 1); 6501 if (numRows) PetscAssertPointer(rows, 3); 6502 6503 PetscCall(PetscMalloc1(numRows, &jdxm)); 6504 for (i = 0; i < numRows; ++i) { 6505 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6506 for (j = 0; j < 3 - sdim; ++j) dxm++; 6507 /* Local index in X dir */ 6508 tmp = *dxm++ - starts[0]; 6509 /* Loop over remaining dimensions */ 6510 for (j = 0; j < dim - 1; ++j) { 6511 /* If nonlocal, set index to be negative */ 6512 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6513 /* Update local index */ 6514 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6515 } 6516 /* Skip component slot if necessary */ 6517 if (mat->stencil.noc) dxm++; 6518 /* Local row number */ 6519 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6520 } 6521 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6522 PetscCall(PetscFree(jdxm)); 6523 PetscFunctionReturn(PETSC_SUCCESS); 6524 } 6525 6526 /*@C 6527 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6528 of a set of rows of a matrix; using local numbering of rows. 6529 6530 Collective 6531 6532 Input Parameters: 6533 + mat - the matrix 6534 . numRows - the number of rows to remove 6535 . rows - the local row indices 6536 . diag - value put in all diagonals of eliminated rows 6537 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6538 - b - optional vector of right-hand side, that will be adjusted by provided solution 6539 6540 Level: intermediate 6541 6542 Notes: 6543 Before calling `MatZeroRowsLocal()`, the user must first set the 6544 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6545 6546 See `MatZeroRows()` for details on how this routine operates. 6547 6548 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6549 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6550 @*/ 6551 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6552 { 6553 PetscFunctionBegin; 6554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6555 PetscValidType(mat, 1); 6556 if (numRows) PetscAssertPointer(rows, 3); 6557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6558 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6559 MatCheckPreallocated(mat, 1); 6560 6561 if (mat->ops->zerorowslocal) { 6562 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6563 } else { 6564 IS is, newis; 6565 const PetscInt *newRows; 6566 6567 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6568 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6569 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6570 PetscCall(ISGetIndices(newis, &newRows)); 6571 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6572 PetscCall(ISRestoreIndices(newis, &newRows)); 6573 PetscCall(ISDestroy(&newis)); 6574 PetscCall(ISDestroy(&is)); 6575 } 6576 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6577 PetscFunctionReturn(PETSC_SUCCESS); 6578 } 6579 6580 /*@ 6581 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6582 of a set of rows of a matrix; using local numbering of rows. 6583 6584 Collective 6585 6586 Input Parameters: 6587 + mat - the matrix 6588 . is - index set of rows to remove 6589 . diag - value put in all diagonals of eliminated rows 6590 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6591 - b - optional vector of right-hand side, that will be adjusted by provided solution 6592 6593 Level: intermediate 6594 6595 Notes: 6596 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6597 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6598 6599 See `MatZeroRows()` for details on how this routine operates. 6600 6601 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6602 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6603 @*/ 6604 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6605 { 6606 PetscInt numRows; 6607 const PetscInt *rows; 6608 6609 PetscFunctionBegin; 6610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6611 PetscValidType(mat, 1); 6612 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6613 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6614 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6615 MatCheckPreallocated(mat, 1); 6616 6617 PetscCall(ISGetLocalSize(is, &numRows)); 6618 PetscCall(ISGetIndices(is, &rows)); 6619 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6620 PetscCall(ISRestoreIndices(is, &rows)); 6621 PetscFunctionReturn(PETSC_SUCCESS); 6622 } 6623 6624 /*@ 6625 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6626 of a set of rows and columns of a matrix; using local numbering of rows. 6627 6628 Collective 6629 6630 Input Parameters: 6631 + mat - the matrix 6632 . numRows - the number of rows to remove 6633 . rows - the global row indices 6634 . diag - value put in all diagonals of eliminated rows 6635 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6636 - b - optional vector of right-hand side, that will be adjusted by provided solution 6637 6638 Level: intermediate 6639 6640 Notes: 6641 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6642 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6643 6644 See `MatZeroRowsColumns()` for details on how this routine operates. 6645 6646 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6647 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6648 @*/ 6649 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6650 { 6651 IS is, newis; 6652 const PetscInt *newRows; 6653 6654 PetscFunctionBegin; 6655 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6656 PetscValidType(mat, 1); 6657 if (numRows) PetscAssertPointer(rows, 3); 6658 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6659 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6660 MatCheckPreallocated(mat, 1); 6661 6662 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6663 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6664 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6665 PetscCall(ISGetIndices(newis, &newRows)); 6666 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6667 PetscCall(ISRestoreIndices(newis, &newRows)); 6668 PetscCall(ISDestroy(&newis)); 6669 PetscCall(ISDestroy(&is)); 6670 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6671 PetscFunctionReturn(PETSC_SUCCESS); 6672 } 6673 6674 /*@ 6675 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6676 of a set of rows and columns of a matrix; using local numbering of rows. 6677 6678 Collective 6679 6680 Input Parameters: 6681 + mat - the matrix 6682 . is - index set of rows to remove 6683 . diag - value put in all diagonals of eliminated rows 6684 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6685 - b - optional vector of right-hand side, that will be adjusted by provided solution 6686 6687 Level: intermediate 6688 6689 Notes: 6690 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6691 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6692 6693 See `MatZeroRowsColumns()` for details on how this routine operates. 6694 6695 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6696 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6697 @*/ 6698 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6699 { 6700 PetscInt numRows; 6701 const PetscInt *rows; 6702 6703 PetscFunctionBegin; 6704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6705 PetscValidType(mat, 1); 6706 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6707 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6708 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6709 MatCheckPreallocated(mat, 1); 6710 6711 PetscCall(ISGetLocalSize(is, &numRows)); 6712 PetscCall(ISGetIndices(is, &rows)); 6713 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6714 PetscCall(ISRestoreIndices(is, &rows)); 6715 PetscFunctionReturn(PETSC_SUCCESS); 6716 } 6717 6718 /*@C 6719 MatGetSize - Returns the numbers of rows and columns in a matrix. 6720 6721 Not Collective 6722 6723 Input Parameter: 6724 . mat - the matrix 6725 6726 Output Parameters: 6727 + m - the number of global rows 6728 - n - the number of global columns 6729 6730 Level: beginner 6731 6732 Note: 6733 Both output parameters can be `NULL` on input. 6734 6735 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6736 @*/ 6737 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6738 { 6739 PetscFunctionBegin; 6740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6741 if (m) *m = mat->rmap->N; 6742 if (n) *n = mat->cmap->N; 6743 PetscFunctionReturn(PETSC_SUCCESS); 6744 } 6745 6746 /*@C 6747 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6748 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6749 6750 Not Collective 6751 6752 Input Parameter: 6753 . mat - the matrix 6754 6755 Output Parameters: 6756 + m - the number of local rows, use `NULL` to not obtain this value 6757 - n - the number of local columns, use `NULL` to not obtain this value 6758 6759 Level: beginner 6760 6761 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6762 @*/ 6763 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6764 { 6765 PetscFunctionBegin; 6766 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6767 if (m) PetscAssertPointer(m, 2); 6768 if (n) PetscAssertPointer(n, 3); 6769 if (m) *m = mat->rmap->n; 6770 if (n) *n = mat->cmap->n; 6771 PetscFunctionReturn(PETSC_SUCCESS); 6772 } 6773 6774 /*@C 6775 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6776 vector one multiplies this matrix by that are owned by this processor. 6777 6778 Not Collective, unless matrix has not been allocated, then collective 6779 6780 Input Parameter: 6781 . mat - the matrix 6782 6783 Output Parameters: 6784 + m - the global index of the first local column, use `NULL` to not obtain this value 6785 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6786 6787 Level: developer 6788 6789 Notes: 6790 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6791 6792 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6793 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6794 6795 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6796 the local values in the matrix. 6797 6798 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6799 Layouts](sec_matlayout) for details on matrix layouts. 6800 6801 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6802 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6803 @*/ 6804 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6805 { 6806 PetscFunctionBegin; 6807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6808 PetscValidType(mat, 1); 6809 if (m) PetscAssertPointer(m, 2); 6810 if (n) PetscAssertPointer(n, 3); 6811 MatCheckPreallocated(mat, 1); 6812 if (m) *m = mat->cmap->rstart; 6813 if (n) *n = mat->cmap->rend; 6814 PetscFunctionReturn(PETSC_SUCCESS); 6815 } 6816 6817 /*@C 6818 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6819 this MPI process. 6820 6821 Not Collective 6822 6823 Input Parameter: 6824 . mat - the matrix 6825 6826 Output Parameters: 6827 + m - the global index of the first local row, use `NULL` to not obtain this value 6828 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6829 6830 Level: beginner 6831 6832 Notes: 6833 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6834 6835 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6836 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6837 6838 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6839 the local values in the matrix. 6840 6841 The high argument is one more than the last element stored locally. 6842 6843 For all matrices it returns the range of matrix rows associated with rows of a vector that 6844 would contain the result of a matrix vector product with this matrix. See [Matrix 6845 Layouts](sec_matlayout) for details on matrix layouts. 6846 6847 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6848 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6849 @*/ 6850 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6851 { 6852 PetscFunctionBegin; 6853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6854 PetscValidType(mat, 1); 6855 if (m) PetscAssertPointer(m, 2); 6856 if (n) PetscAssertPointer(n, 3); 6857 MatCheckPreallocated(mat, 1); 6858 if (m) *m = mat->rmap->rstart; 6859 if (n) *n = mat->rmap->rend; 6860 PetscFunctionReturn(PETSC_SUCCESS); 6861 } 6862 6863 /*@C 6864 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6865 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6866 6867 Not Collective, unless matrix has not been allocated 6868 6869 Input Parameter: 6870 . mat - the matrix 6871 6872 Output Parameter: 6873 . ranges - start of each processors portion plus one more than the total length at the end 6874 6875 Level: beginner 6876 6877 Notes: 6878 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6879 6880 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6881 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6882 6883 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6884 the local values in the matrix. 6885 6886 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6887 would contain the result of a matrix vector product with this matrix. See [Matrix 6888 Layouts](sec_matlayout) for details on matrix layouts. 6889 6890 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6891 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6892 `DMDAGetGhostCorners()`, `DM` 6893 @*/ 6894 PetscErrorCode MatGetOwnershipRanges(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->rmap, ranges)); 6901 PetscFunctionReturn(PETSC_SUCCESS); 6902 } 6903 6904 /*@C 6905 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6906 vector one multiplies this vector by that are owned by each processor. 6907 6908 Not Collective, unless matrix has not been allocated 6909 6910 Input Parameter: 6911 . mat - the matrix 6912 6913 Output Parameter: 6914 . ranges - start of each processors portion plus one more than the total length at the end 6915 6916 Level: beginner 6917 6918 Notes: 6919 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6920 6921 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6922 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6923 6924 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6925 the local values in the matrix. 6926 6927 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6928 Layouts](sec_matlayout) for details on matrix layouts. 6929 6930 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6931 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6932 `DMDAGetGhostCorners()`, `DM` 6933 @*/ 6934 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6935 { 6936 PetscFunctionBegin; 6937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6938 PetscValidType(mat, 1); 6939 MatCheckPreallocated(mat, 1); 6940 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6941 PetscFunctionReturn(PETSC_SUCCESS); 6942 } 6943 6944 /*@C 6945 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6946 6947 Not Collective 6948 6949 Input Parameter: 6950 . A - matrix 6951 6952 Output Parameters: 6953 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6954 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6955 6956 Level: intermediate 6957 6958 Note: 6959 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6960 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6961 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6962 details on matrix layouts. 6963 6964 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 6965 @*/ 6966 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6967 { 6968 PetscErrorCode (*f)(Mat, IS *, IS *); 6969 6970 PetscFunctionBegin; 6971 MatCheckPreallocated(A, 1); 6972 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6973 if (f) { 6974 PetscCall((*f)(A, rows, cols)); 6975 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6976 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6977 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6978 } 6979 PetscFunctionReturn(PETSC_SUCCESS); 6980 } 6981 6982 /*@C 6983 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6984 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6985 to complete the factorization. 6986 6987 Collective 6988 6989 Input Parameters: 6990 + fact - the factorized matrix obtained with `MatGetFactor()` 6991 . mat - the matrix 6992 . row - row permutation 6993 . col - column permutation 6994 - info - structure containing 6995 .vb 6996 levels - number of levels of fill. 6997 expected fill - as ratio of original fill. 6998 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6999 missing diagonal entries) 7000 .ve 7001 7002 Level: developer 7003 7004 Notes: 7005 See [Matrix Factorization](sec_matfactor) for additional information. 7006 7007 Most users should employ the `KSP` interface for linear solvers 7008 instead of working directly with matrix algebra routines such as this. 7009 See, e.g., `KSPCreate()`. 7010 7011 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7012 7013 Developer Note: 7014 The Fortran interface is not autogenerated as the 7015 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7016 7017 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7018 `MatGetOrdering()`, `MatFactorInfo` 7019 @*/ 7020 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7021 { 7022 PetscFunctionBegin; 7023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7024 PetscValidType(mat, 2); 7025 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7026 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7027 PetscAssertPointer(info, 5); 7028 PetscAssertPointer(fact, 1); 7029 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7030 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7031 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7032 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7033 MatCheckPreallocated(mat, 2); 7034 7035 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7036 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7037 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7038 PetscFunctionReturn(PETSC_SUCCESS); 7039 } 7040 7041 /*@C 7042 MatICCFactorSymbolic - Performs symbolic incomplete 7043 Cholesky factorization for a symmetric matrix. Use 7044 `MatCholeskyFactorNumeric()` to complete the factorization. 7045 7046 Collective 7047 7048 Input Parameters: 7049 + fact - the factorized matrix obtained with `MatGetFactor()` 7050 . mat - the matrix to be factored 7051 . perm - row and column permutation 7052 - info - structure containing 7053 .vb 7054 levels - number of levels of fill. 7055 expected fill - as ratio of original fill. 7056 .ve 7057 7058 Level: developer 7059 7060 Notes: 7061 Most users should employ the `KSP` interface for linear solvers 7062 instead of working directly with matrix algebra routines such as this. 7063 See, e.g., `KSPCreate()`. 7064 7065 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7066 7067 Developer Note: 7068 The Fortran interface is not autogenerated as the 7069 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7070 7071 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7072 @*/ 7073 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7074 { 7075 PetscFunctionBegin; 7076 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7077 PetscValidType(mat, 2); 7078 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7079 PetscAssertPointer(info, 4); 7080 PetscAssertPointer(fact, 1); 7081 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7082 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7083 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7084 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7085 MatCheckPreallocated(mat, 2); 7086 7087 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7088 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7089 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7090 PetscFunctionReturn(PETSC_SUCCESS); 7091 } 7092 7093 /*@C 7094 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7095 points to an array of valid matrices, they may be reused to store the new 7096 submatrices. 7097 7098 Collective 7099 7100 Input Parameters: 7101 + mat - the matrix 7102 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7103 . irow - index set of rows to extract 7104 . icol - index set of columns to extract 7105 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7106 7107 Output Parameter: 7108 . submat - the array of submatrices 7109 7110 Level: advanced 7111 7112 Notes: 7113 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7114 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7115 to extract a parallel submatrix. 7116 7117 Some matrix types place restrictions on the row and column 7118 indices, such as that they be sorted or that they be equal to each other. 7119 7120 The index sets may not have duplicate entries. 7121 7122 When extracting submatrices from a parallel matrix, each processor can 7123 form a different submatrix by setting the rows and columns of its 7124 individual index sets according to the local submatrix desired. 7125 7126 When finished using the submatrices, the user should destroy 7127 them with `MatDestroySubMatrices()`. 7128 7129 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7130 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7131 7132 This routine creates the matrices in submat; you should NOT create them before 7133 calling it. It also allocates the array of matrix pointers submat. 7134 7135 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7136 request one row/column in a block, they must request all rows/columns that are in 7137 that block. For example, if the block size is 2 you cannot request just row 0 and 7138 column 0. 7139 7140 Fortran Note: 7141 The Fortran interface is slightly different from that given below; it 7142 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7143 7144 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7145 @*/ 7146 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7147 { 7148 PetscInt i; 7149 PetscBool eq; 7150 7151 PetscFunctionBegin; 7152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7153 PetscValidType(mat, 1); 7154 if (n) { 7155 PetscAssertPointer(irow, 3); 7156 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7157 PetscAssertPointer(icol, 4); 7158 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7159 } 7160 PetscAssertPointer(submat, 6); 7161 if (n && scall == MAT_REUSE_MATRIX) { 7162 PetscAssertPointer(*submat, 6); 7163 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7164 } 7165 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7166 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7167 MatCheckPreallocated(mat, 1); 7168 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7169 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7170 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7171 for (i = 0; i < n; i++) { 7172 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7173 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7174 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7175 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7176 if (mat->boundtocpu && mat->bindingpropagates) { 7177 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7178 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7179 } 7180 #endif 7181 } 7182 PetscFunctionReturn(PETSC_SUCCESS); 7183 } 7184 7185 /*@C 7186 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7187 7188 Collective 7189 7190 Input Parameters: 7191 + mat - the matrix 7192 . n - the number of submatrixes to be extracted 7193 . irow - index set of rows to extract 7194 . icol - index set of columns to extract 7195 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7196 7197 Output Parameter: 7198 . submat - the array of submatrices 7199 7200 Level: advanced 7201 7202 Note: 7203 This is used by `PCGASM` 7204 7205 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7206 @*/ 7207 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7208 { 7209 PetscInt i; 7210 PetscBool eq; 7211 7212 PetscFunctionBegin; 7213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7214 PetscValidType(mat, 1); 7215 if (n) { 7216 PetscAssertPointer(irow, 3); 7217 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7218 PetscAssertPointer(icol, 4); 7219 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7220 } 7221 PetscAssertPointer(submat, 6); 7222 if (n && scall == MAT_REUSE_MATRIX) { 7223 PetscAssertPointer(*submat, 6); 7224 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7225 } 7226 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7227 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7228 MatCheckPreallocated(mat, 1); 7229 7230 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7231 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7232 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7233 for (i = 0; i < n; i++) { 7234 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7235 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7236 } 7237 PetscFunctionReturn(PETSC_SUCCESS); 7238 } 7239 7240 /*@C 7241 MatDestroyMatrices - Destroys an array of matrices. 7242 7243 Collective 7244 7245 Input Parameters: 7246 + n - the number of local matrices 7247 - mat - the matrices (this is a pointer to the array of matrices) 7248 7249 Level: advanced 7250 7251 Note: 7252 Frees not only the matrices, but also the array that contains the matrices 7253 7254 Fortran Note: 7255 This does not free the array. 7256 7257 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7258 @*/ 7259 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7260 { 7261 PetscInt i; 7262 7263 PetscFunctionBegin; 7264 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7265 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7266 PetscAssertPointer(mat, 2); 7267 7268 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7269 7270 /* memory is allocated even if n = 0 */ 7271 PetscCall(PetscFree(*mat)); 7272 PetscFunctionReturn(PETSC_SUCCESS); 7273 } 7274 7275 /*@C 7276 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7277 7278 Collective 7279 7280 Input Parameters: 7281 + n - the number of local matrices 7282 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7283 sequence of `MatCreateSubMatrices()`) 7284 7285 Level: advanced 7286 7287 Note: 7288 Frees not only the matrices, but also the array that contains the matrices 7289 7290 Fortran Note: 7291 This does not free the array. 7292 7293 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7294 @*/ 7295 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7296 { 7297 Mat mat0; 7298 7299 PetscFunctionBegin; 7300 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7301 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7302 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7303 PetscAssertPointer(mat, 2); 7304 7305 mat0 = (*mat)[0]; 7306 if (mat0 && mat0->ops->destroysubmatrices) { 7307 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7308 } else { 7309 PetscCall(MatDestroyMatrices(n, mat)); 7310 } 7311 PetscFunctionReturn(PETSC_SUCCESS); 7312 } 7313 7314 /*@C 7315 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7316 7317 Collective 7318 7319 Input Parameter: 7320 . mat - the matrix 7321 7322 Output Parameter: 7323 . matstruct - the sequential matrix with the nonzero structure of `mat` 7324 7325 Level: developer 7326 7327 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7328 @*/ 7329 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7330 { 7331 PetscFunctionBegin; 7332 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7333 PetscAssertPointer(matstruct, 2); 7334 7335 PetscValidType(mat, 1); 7336 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7337 MatCheckPreallocated(mat, 1); 7338 7339 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7340 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7341 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7342 PetscFunctionReturn(PETSC_SUCCESS); 7343 } 7344 7345 /*@C 7346 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7347 7348 Collective 7349 7350 Input Parameter: 7351 . mat - the matrix 7352 7353 Level: advanced 7354 7355 Note: 7356 This is not needed, one can just call `MatDestroy()` 7357 7358 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7359 @*/ 7360 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7361 { 7362 PetscFunctionBegin; 7363 PetscAssertPointer(mat, 1); 7364 PetscCall(MatDestroy(mat)); 7365 PetscFunctionReturn(PETSC_SUCCESS); 7366 } 7367 7368 /*@ 7369 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7370 replaces the index sets by larger ones that represent submatrices with 7371 additional overlap. 7372 7373 Collective 7374 7375 Input Parameters: 7376 + mat - the matrix 7377 . n - the number of index sets 7378 . is - the array of index sets (these index sets will changed during the call) 7379 - ov - the additional overlap requested 7380 7381 Options Database Key: 7382 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7383 7384 Level: developer 7385 7386 Note: 7387 The computed overlap preserves the matrix block sizes when the blocks are square. 7388 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7389 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7390 7391 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7392 @*/ 7393 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7394 { 7395 PetscInt i, bs, cbs; 7396 7397 PetscFunctionBegin; 7398 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7399 PetscValidType(mat, 1); 7400 PetscValidLogicalCollectiveInt(mat, n, 2); 7401 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7402 if (n) { 7403 PetscAssertPointer(is, 3); 7404 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7405 } 7406 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7407 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7408 MatCheckPreallocated(mat, 1); 7409 7410 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7411 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7412 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7413 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7414 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7415 if (bs == cbs) { 7416 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7417 } 7418 PetscFunctionReturn(PETSC_SUCCESS); 7419 } 7420 7421 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7422 7423 /*@ 7424 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7425 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7426 additional overlap. 7427 7428 Collective 7429 7430 Input Parameters: 7431 + mat - the matrix 7432 . n - the number of index sets 7433 . is - the array of index sets (these index sets will changed during the call) 7434 - ov - the additional overlap requested 7435 7436 ` Options Database Key: 7437 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7438 7439 Level: developer 7440 7441 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7442 @*/ 7443 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7444 { 7445 PetscInt i; 7446 7447 PetscFunctionBegin; 7448 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7449 PetscValidType(mat, 1); 7450 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7451 if (n) { 7452 PetscAssertPointer(is, 3); 7453 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7454 } 7455 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7456 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7457 MatCheckPreallocated(mat, 1); 7458 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7459 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7460 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7461 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7462 PetscFunctionReturn(PETSC_SUCCESS); 7463 } 7464 7465 /*@ 7466 MatGetBlockSize - Returns the matrix block size. 7467 7468 Not Collective 7469 7470 Input Parameter: 7471 . mat - the matrix 7472 7473 Output Parameter: 7474 . bs - block size 7475 7476 Level: intermediate 7477 7478 Notes: 7479 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7480 7481 If the block size has not been set yet this routine returns 1. 7482 7483 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7484 @*/ 7485 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7486 { 7487 PetscFunctionBegin; 7488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7489 PetscAssertPointer(bs, 2); 7490 *bs = PetscAbs(mat->rmap->bs); 7491 PetscFunctionReturn(PETSC_SUCCESS); 7492 } 7493 7494 /*@ 7495 MatGetBlockSizes - Returns the matrix block row and column sizes. 7496 7497 Not Collective 7498 7499 Input Parameter: 7500 . mat - the matrix 7501 7502 Output Parameters: 7503 + rbs - row block size 7504 - cbs - column block size 7505 7506 Level: intermediate 7507 7508 Notes: 7509 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7510 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7511 7512 If a block size has not been set yet this routine returns 1. 7513 7514 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7515 @*/ 7516 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7517 { 7518 PetscFunctionBegin; 7519 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7520 if (rbs) PetscAssertPointer(rbs, 2); 7521 if (cbs) PetscAssertPointer(cbs, 3); 7522 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7523 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7524 PetscFunctionReturn(PETSC_SUCCESS); 7525 } 7526 7527 /*@ 7528 MatSetBlockSize - Sets the matrix block size. 7529 7530 Logically Collective 7531 7532 Input Parameters: 7533 + mat - the matrix 7534 - bs - block size 7535 7536 Level: intermediate 7537 7538 Notes: 7539 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7540 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7541 7542 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7543 is compatible with the matrix local sizes. 7544 7545 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7546 @*/ 7547 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7548 { 7549 PetscFunctionBegin; 7550 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7551 PetscValidLogicalCollectiveInt(mat, bs, 2); 7552 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7553 PetscFunctionReturn(PETSC_SUCCESS); 7554 } 7555 7556 typedef struct { 7557 PetscInt n; 7558 IS *is; 7559 Mat *mat; 7560 PetscObjectState nonzerostate; 7561 Mat C; 7562 } EnvelopeData; 7563 7564 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7565 { 7566 EnvelopeData *edata = (EnvelopeData *)ptr; 7567 7568 PetscFunctionBegin; 7569 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7570 PetscCall(PetscFree(edata->is)); 7571 PetscCall(PetscFree(edata)); 7572 PetscFunctionReturn(PETSC_SUCCESS); 7573 } 7574 7575 /*@ 7576 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7577 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7578 7579 Collective 7580 7581 Input Parameter: 7582 . mat - the matrix 7583 7584 Level: intermediate 7585 7586 Notes: 7587 There can be zeros within the blocks 7588 7589 The blocks can overlap between processes, including laying on more than two processes 7590 7591 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7592 @*/ 7593 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7594 { 7595 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7596 PetscInt *diag, *odiag, sc; 7597 VecScatter scatter; 7598 PetscScalar *seqv; 7599 const PetscScalar *parv; 7600 const PetscInt *ia, *ja; 7601 PetscBool set, flag, done; 7602 Mat AA = mat, A; 7603 MPI_Comm comm; 7604 PetscMPIInt rank, size, tag; 7605 MPI_Status status; 7606 PetscContainer container; 7607 EnvelopeData *edata; 7608 Vec seq, par; 7609 IS isglobal; 7610 7611 PetscFunctionBegin; 7612 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7613 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7614 if (!set || !flag) { 7615 /* TODO: only needs nonzero structure of transpose */ 7616 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7617 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7618 } 7619 PetscCall(MatAIJGetLocalMat(AA, &A)); 7620 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7621 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7622 7623 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7624 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7625 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7626 PetscCallMPI(MPI_Comm_size(comm, &size)); 7627 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7628 7629 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7630 7631 if (rank > 0) { 7632 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7633 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7634 } 7635 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7636 for (i = 0; i < n; i++) { 7637 env = PetscMax(env, ja[ia[i + 1] - 1]); 7638 II = rstart + i; 7639 if (env == II) { 7640 starts[lblocks] = tbs; 7641 sizes[lblocks++] = 1 + II - tbs; 7642 tbs = 1 + II; 7643 } 7644 } 7645 if (rank < size - 1) { 7646 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7647 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7648 } 7649 7650 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7651 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7652 PetscCall(MatDestroy(&A)); 7653 7654 PetscCall(PetscNew(&edata)); 7655 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7656 edata->n = lblocks; 7657 /* create IS needed for extracting blocks from the original matrix */ 7658 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7659 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7660 7661 /* Create the resulting inverse matrix structure with preallocation information */ 7662 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7663 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7664 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7665 PetscCall(MatSetType(edata->C, MATAIJ)); 7666 7667 /* Communicate the start and end of each row, from each block to the correct rank */ 7668 /* TODO: Use PetscSF instead of VecScatter */ 7669 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7670 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7671 PetscCall(VecGetArrayWrite(seq, &seqv)); 7672 for (PetscInt i = 0; i < lblocks; i++) { 7673 for (PetscInt j = 0; j < sizes[i]; j++) { 7674 seqv[cnt] = starts[i]; 7675 seqv[cnt + 1] = starts[i] + sizes[i]; 7676 cnt += 2; 7677 } 7678 } 7679 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7680 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7681 sc -= cnt; 7682 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7683 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7684 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7685 PetscCall(ISDestroy(&isglobal)); 7686 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7687 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7688 PetscCall(VecScatterDestroy(&scatter)); 7689 PetscCall(VecDestroy(&seq)); 7690 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7691 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7692 PetscCall(VecGetArrayRead(par, &parv)); 7693 cnt = 0; 7694 PetscCall(MatGetSize(mat, NULL, &n)); 7695 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7696 PetscInt start, end, d = 0, od = 0; 7697 7698 start = (PetscInt)PetscRealPart(parv[cnt]); 7699 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7700 cnt += 2; 7701 7702 if (start < cstart) { 7703 od += cstart - start + n - cend; 7704 d += cend - cstart; 7705 } else if (start < cend) { 7706 od += n - cend; 7707 d += cend - start; 7708 } else od += n - start; 7709 if (end <= cstart) { 7710 od -= cstart - end + n - cend; 7711 d -= cend - cstart; 7712 } else if (end < cend) { 7713 od -= n - cend; 7714 d -= cend - end; 7715 } else od -= n - end; 7716 7717 odiag[i] = od; 7718 diag[i] = d; 7719 } 7720 PetscCall(VecRestoreArrayRead(par, &parv)); 7721 PetscCall(VecDestroy(&par)); 7722 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7723 PetscCall(PetscFree2(diag, odiag)); 7724 PetscCall(PetscFree2(sizes, starts)); 7725 7726 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7727 PetscCall(PetscContainerSetPointer(container, edata)); 7728 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7729 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7730 PetscCall(PetscObjectDereference((PetscObject)container)); 7731 PetscFunctionReturn(PETSC_SUCCESS); 7732 } 7733 7734 /*@ 7735 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7736 7737 Collective 7738 7739 Input Parameters: 7740 + A - the matrix 7741 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7742 7743 Output Parameter: 7744 . C - matrix with inverted block diagonal of `A` 7745 7746 Level: advanced 7747 7748 Note: 7749 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7750 7751 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7752 @*/ 7753 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7754 { 7755 PetscContainer container; 7756 EnvelopeData *edata; 7757 PetscObjectState nonzerostate; 7758 7759 PetscFunctionBegin; 7760 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7761 if (!container) { 7762 PetscCall(MatComputeVariableBlockEnvelope(A)); 7763 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7764 } 7765 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7766 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7767 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7768 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7769 7770 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7771 *C = edata->C; 7772 7773 for (PetscInt i = 0; i < edata->n; i++) { 7774 Mat D; 7775 PetscScalar *dvalues; 7776 7777 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7778 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7779 PetscCall(MatSeqDenseInvert(D)); 7780 PetscCall(MatDenseGetArray(D, &dvalues)); 7781 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7782 PetscCall(MatDestroy(&D)); 7783 } 7784 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7785 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7786 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7787 PetscFunctionReturn(PETSC_SUCCESS); 7788 } 7789 7790 /*@ 7791 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7792 7793 Not Collective 7794 7795 Input Parameters: 7796 + mat - the matrix 7797 . nblocks - the number of blocks on this process, each block can only exist on a single process 7798 - bsizes - the block sizes 7799 7800 Level: intermediate 7801 7802 Notes: 7803 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7804 7805 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. 7806 7807 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7808 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7809 @*/ 7810 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7811 { 7812 PetscInt ncnt = 0, nlocal; 7813 7814 PetscFunctionBegin; 7815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7816 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7817 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); 7818 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7819 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); 7820 PetscCall(PetscFree(mat->bsizes)); 7821 mat->nblocks = nblocks; 7822 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7823 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7824 PetscFunctionReturn(PETSC_SUCCESS); 7825 } 7826 7827 /*@C 7828 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7829 7830 Not Collective; No Fortran Support 7831 7832 Input Parameter: 7833 . mat - the matrix 7834 7835 Output Parameters: 7836 + nblocks - the number of blocks on this process 7837 - bsizes - the block sizes 7838 7839 Level: intermediate 7840 7841 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7842 @*/ 7843 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7844 { 7845 PetscFunctionBegin; 7846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7847 if (nblocks) *nblocks = mat->nblocks; 7848 if (bsizes) *bsizes = mat->bsizes; 7849 PetscFunctionReturn(PETSC_SUCCESS); 7850 } 7851 7852 /*@ 7853 MatSetBlockSizes - Sets the matrix block row and column sizes. 7854 7855 Logically Collective 7856 7857 Input Parameters: 7858 + mat - the matrix 7859 . rbs - row block size 7860 - cbs - column block size 7861 7862 Level: intermediate 7863 7864 Notes: 7865 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7866 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7867 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7868 7869 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7870 are compatible with the matrix local sizes. 7871 7872 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7873 7874 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7875 @*/ 7876 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7877 { 7878 PetscFunctionBegin; 7879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7880 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7881 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7882 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7883 if (mat->rmap->refcnt) { 7884 ISLocalToGlobalMapping l2g = NULL; 7885 PetscLayout nmap = NULL; 7886 7887 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7888 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7889 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7890 mat->rmap = nmap; 7891 mat->rmap->mapping = l2g; 7892 } 7893 if (mat->cmap->refcnt) { 7894 ISLocalToGlobalMapping l2g = NULL; 7895 PetscLayout nmap = NULL; 7896 7897 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7898 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7899 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7900 mat->cmap = nmap; 7901 mat->cmap->mapping = l2g; 7902 } 7903 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7904 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7905 PetscFunctionReturn(PETSC_SUCCESS); 7906 } 7907 7908 /*@ 7909 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7910 7911 Logically Collective 7912 7913 Input Parameters: 7914 + mat - the matrix 7915 . fromRow - matrix from which to copy row block size 7916 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7917 7918 Level: developer 7919 7920 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7921 @*/ 7922 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7923 { 7924 PetscFunctionBegin; 7925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7926 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7927 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7928 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7929 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7930 PetscFunctionReturn(PETSC_SUCCESS); 7931 } 7932 7933 /*@ 7934 MatResidual - Default routine to calculate the residual r = b - Ax 7935 7936 Collective 7937 7938 Input Parameters: 7939 + mat - the matrix 7940 . b - the right-hand-side 7941 - x - the approximate solution 7942 7943 Output Parameter: 7944 . r - location to store the residual 7945 7946 Level: developer 7947 7948 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7949 @*/ 7950 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7951 { 7952 PetscFunctionBegin; 7953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7954 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7955 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7956 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7957 PetscValidType(mat, 1); 7958 MatCheckPreallocated(mat, 1); 7959 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7960 if (!mat->ops->residual) { 7961 PetscCall(MatMult(mat, x, r)); 7962 PetscCall(VecAYPX(r, -1.0, b)); 7963 } else { 7964 PetscUseTypeMethod(mat, residual, b, x, r); 7965 } 7966 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7967 PetscFunctionReturn(PETSC_SUCCESS); 7968 } 7969 7970 /*MC 7971 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7972 7973 Synopsis: 7974 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7975 7976 Not Collective 7977 7978 Input Parameters: 7979 + A - the matrix 7980 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7981 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7982 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7983 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7984 always used. 7985 7986 Output Parameters: 7987 + n - number of local rows in the (possibly compressed) matrix 7988 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7989 . ja - the column indices 7990 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7991 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7992 7993 Level: developer 7994 7995 Note: 7996 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7997 7998 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7999 M*/ 8000 8001 /*MC 8002 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8003 8004 Synopsis: 8005 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8006 8007 Not Collective 8008 8009 Input Parameters: 8010 + A - the matrix 8011 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8012 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8013 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8014 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8015 always used. 8016 . n - number of local rows in the (possibly compressed) matrix 8017 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8018 . ja - the column indices 8019 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8020 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8021 8022 Level: developer 8023 8024 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8025 M*/ 8026 8027 /*@C 8028 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8029 8030 Collective 8031 8032 Input Parameters: 8033 + mat - the matrix 8034 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8035 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8036 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8037 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8038 always used. 8039 8040 Output Parameters: 8041 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8042 . 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 8043 . ja - the column indices, use `NULL` if not needed 8044 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8045 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8046 8047 Level: developer 8048 8049 Notes: 8050 You CANNOT change any of the ia[] or ja[] values. 8051 8052 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8053 8054 Fortran Notes: 8055 Use 8056 .vb 8057 PetscInt, pointer :: ia(:),ja(:) 8058 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8059 ! Access the ith and jth entries via ia(i) and ja(j) 8060 .ve 8061 8062 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8063 8064 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8065 @*/ 8066 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8067 { 8068 PetscFunctionBegin; 8069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8070 PetscValidType(mat, 1); 8071 if (n) PetscAssertPointer(n, 5); 8072 if (ia) PetscAssertPointer(ia, 6); 8073 if (ja) PetscAssertPointer(ja, 7); 8074 if (done) PetscAssertPointer(done, 8); 8075 MatCheckPreallocated(mat, 1); 8076 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8077 else { 8078 if (done) *done = PETSC_TRUE; 8079 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8080 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8081 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8082 } 8083 PetscFunctionReturn(PETSC_SUCCESS); 8084 } 8085 8086 /*@C 8087 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8088 8089 Collective 8090 8091 Input Parameters: 8092 + mat - the matrix 8093 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8094 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8095 symmetrized 8096 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8097 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8098 always used. 8099 . n - number of columns in the (possibly compressed) matrix 8100 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8101 - ja - the row indices 8102 8103 Output Parameter: 8104 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8105 8106 Level: developer 8107 8108 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8109 @*/ 8110 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8111 { 8112 PetscFunctionBegin; 8113 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8114 PetscValidType(mat, 1); 8115 PetscAssertPointer(n, 5); 8116 if (ia) PetscAssertPointer(ia, 6); 8117 if (ja) PetscAssertPointer(ja, 7); 8118 PetscAssertPointer(done, 8); 8119 MatCheckPreallocated(mat, 1); 8120 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8121 else { 8122 *done = PETSC_TRUE; 8123 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8124 } 8125 PetscFunctionReturn(PETSC_SUCCESS); 8126 } 8127 8128 /*@C 8129 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8130 8131 Collective 8132 8133 Input Parameters: 8134 + mat - the matrix 8135 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8136 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8137 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8138 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8139 always used. 8140 . n - size of (possibly compressed) matrix 8141 . ia - the row pointers 8142 - ja - the column indices 8143 8144 Output Parameter: 8145 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8146 8147 Level: developer 8148 8149 Note: 8150 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8151 us of the array after it has been restored. If you pass `NULL`, it will 8152 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8153 8154 Fortran Note: 8155 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8156 8157 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8158 @*/ 8159 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8160 { 8161 PetscFunctionBegin; 8162 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8163 PetscValidType(mat, 1); 8164 if (ia) PetscAssertPointer(ia, 6); 8165 if (ja) PetscAssertPointer(ja, 7); 8166 if (done) PetscAssertPointer(done, 8); 8167 MatCheckPreallocated(mat, 1); 8168 8169 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8170 else { 8171 if (done) *done = PETSC_TRUE; 8172 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8173 if (n) *n = 0; 8174 if (ia) *ia = NULL; 8175 if (ja) *ja = NULL; 8176 } 8177 PetscFunctionReturn(PETSC_SUCCESS); 8178 } 8179 8180 /*@C 8181 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8182 8183 Collective 8184 8185 Input Parameters: 8186 + mat - the matrix 8187 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8188 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8189 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8190 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8191 always used. 8192 8193 Output Parameters: 8194 + n - size of (possibly compressed) matrix 8195 . ia - the column pointers 8196 . ja - the row indices 8197 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8198 8199 Level: developer 8200 8201 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8202 @*/ 8203 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8204 { 8205 PetscFunctionBegin; 8206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8207 PetscValidType(mat, 1); 8208 if (ia) PetscAssertPointer(ia, 6); 8209 if (ja) PetscAssertPointer(ja, 7); 8210 PetscAssertPointer(done, 8); 8211 MatCheckPreallocated(mat, 1); 8212 8213 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8214 else { 8215 *done = PETSC_TRUE; 8216 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8217 if (n) *n = 0; 8218 if (ia) *ia = NULL; 8219 if (ja) *ja = NULL; 8220 } 8221 PetscFunctionReturn(PETSC_SUCCESS); 8222 } 8223 8224 /*@C 8225 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8226 `MatGetColumnIJ()`. 8227 8228 Collective 8229 8230 Input Parameters: 8231 + mat - the matrix 8232 . ncolors - maximum color value 8233 . n - number of entries in colorarray 8234 - colorarray - array indicating color for each column 8235 8236 Output Parameter: 8237 . iscoloring - coloring generated using colorarray information 8238 8239 Level: developer 8240 8241 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8242 @*/ 8243 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8244 { 8245 PetscFunctionBegin; 8246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8247 PetscValidType(mat, 1); 8248 PetscAssertPointer(colorarray, 4); 8249 PetscAssertPointer(iscoloring, 5); 8250 MatCheckPreallocated(mat, 1); 8251 8252 if (!mat->ops->coloringpatch) { 8253 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8254 } else { 8255 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8256 } 8257 PetscFunctionReturn(PETSC_SUCCESS); 8258 } 8259 8260 /*@ 8261 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8262 8263 Logically Collective 8264 8265 Input Parameter: 8266 . mat - the factored matrix to be reset 8267 8268 Level: developer 8269 8270 Notes: 8271 This routine should be used only with factored matrices formed by in-place 8272 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8273 format). This option can save memory, for example, when solving nonlinear 8274 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8275 ILU(0) preconditioner. 8276 8277 One can specify in-place ILU(0) factorization by calling 8278 .vb 8279 PCType(pc,PCILU); 8280 PCFactorSeUseInPlace(pc); 8281 .ve 8282 or by using the options -pc_type ilu -pc_factor_in_place 8283 8284 In-place factorization ILU(0) can also be used as a local 8285 solver for the blocks within the block Jacobi or additive Schwarz 8286 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8287 for details on setting local solver options. 8288 8289 Most users should employ the `KSP` interface for linear solvers 8290 instead of working directly with matrix algebra routines such as this. 8291 See, e.g., `KSPCreate()`. 8292 8293 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8294 @*/ 8295 PetscErrorCode MatSetUnfactored(Mat mat) 8296 { 8297 PetscFunctionBegin; 8298 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8299 PetscValidType(mat, 1); 8300 MatCheckPreallocated(mat, 1); 8301 mat->factortype = MAT_FACTOR_NONE; 8302 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8303 PetscUseTypeMethod(mat, setunfactored); 8304 PetscFunctionReturn(PETSC_SUCCESS); 8305 } 8306 8307 /*MC 8308 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8309 8310 Synopsis: 8311 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8312 8313 Not Collective 8314 8315 Input Parameter: 8316 . x - matrix 8317 8318 Output Parameters: 8319 + xx_v - the Fortran pointer to the array 8320 - ierr - error code 8321 8322 Example of Usage: 8323 .vb 8324 PetscScalar, pointer xx_v(:,:) 8325 .... 8326 call MatDenseGetArrayF90(x,xx_v,ierr) 8327 a = xx_v(3) 8328 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8329 .ve 8330 8331 Level: advanced 8332 8333 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8334 M*/ 8335 8336 /*MC 8337 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8338 accessed with `MatDenseGetArrayF90()`. 8339 8340 Synopsis: 8341 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8342 8343 Not Collective 8344 8345 Input Parameters: 8346 + x - matrix 8347 - xx_v - the Fortran90 pointer to the array 8348 8349 Output Parameter: 8350 . ierr - error code 8351 8352 Example of Usage: 8353 .vb 8354 PetscScalar, pointer xx_v(:,:) 8355 .... 8356 call MatDenseGetArrayF90(x,xx_v,ierr) 8357 a = xx_v(3) 8358 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8359 .ve 8360 8361 Level: advanced 8362 8363 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8364 M*/ 8365 8366 /*MC 8367 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8368 8369 Synopsis: 8370 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8371 8372 Not Collective 8373 8374 Input Parameter: 8375 . x - matrix 8376 8377 Output Parameters: 8378 + xx_v - the Fortran pointer to the array 8379 - ierr - error code 8380 8381 Example of Usage: 8382 .vb 8383 PetscScalar, pointer xx_v(:) 8384 .... 8385 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8386 a = xx_v(3) 8387 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8388 .ve 8389 8390 Level: advanced 8391 8392 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8393 M*/ 8394 8395 /*MC 8396 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8397 accessed with `MatSeqAIJGetArrayF90()`. 8398 8399 Synopsis: 8400 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8401 8402 Not Collective 8403 8404 Input Parameters: 8405 + x - matrix 8406 - xx_v - the Fortran90 pointer to the array 8407 8408 Output Parameter: 8409 . ierr - error code 8410 8411 Example of Usage: 8412 .vb 8413 PetscScalar, pointer xx_v(:) 8414 .... 8415 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8416 a = xx_v(3) 8417 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8418 .ve 8419 8420 Level: advanced 8421 8422 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8423 M*/ 8424 8425 /*@ 8426 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8427 as the original matrix. 8428 8429 Collective 8430 8431 Input Parameters: 8432 + mat - the original matrix 8433 . isrow - parallel `IS` containing the rows this processor should obtain 8434 . 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. 8435 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8436 8437 Output Parameter: 8438 . newmat - the new submatrix, of the same type as the original matrix 8439 8440 Level: advanced 8441 8442 Notes: 8443 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8444 8445 Some matrix types place restrictions on the row and column indices, such 8446 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; 8447 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8448 8449 The index sets may not have duplicate entries. 8450 8451 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8452 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8453 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8454 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8455 you are finished using it. 8456 8457 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8458 the input matrix. 8459 8460 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8461 8462 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8463 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8464 8465 Example usage: 8466 Consider the following 8x8 matrix with 34 non-zero values, that is 8467 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8468 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8469 as follows 8470 .vb 8471 1 2 0 | 0 3 0 | 0 4 8472 Proc0 0 5 6 | 7 0 0 | 8 0 8473 9 0 10 | 11 0 0 | 12 0 8474 ------------------------------------- 8475 13 0 14 | 15 16 17 | 0 0 8476 Proc1 0 18 0 | 19 20 21 | 0 0 8477 0 0 0 | 22 23 0 | 24 0 8478 ------------------------------------- 8479 Proc2 25 26 27 | 0 0 28 | 29 0 8480 30 0 0 | 31 32 33 | 0 34 8481 .ve 8482 8483 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8484 8485 .vb 8486 2 0 | 0 3 0 | 0 8487 Proc0 5 6 | 7 0 0 | 8 8488 ------------------------------- 8489 Proc1 18 0 | 19 20 21 | 0 8490 ------------------------------- 8491 Proc2 26 27 | 0 0 28 | 29 8492 0 0 | 31 32 33 | 0 8493 .ve 8494 8495 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8496 @*/ 8497 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8498 { 8499 PetscMPIInt size; 8500 Mat *local; 8501 IS iscoltmp; 8502 PetscBool flg; 8503 8504 PetscFunctionBegin; 8505 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8506 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8507 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8508 PetscAssertPointer(newmat, 5); 8509 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8510 PetscValidType(mat, 1); 8511 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8512 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8513 8514 MatCheckPreallocated(mat, 1); 8515 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8516 8517 if (!iscol || isrow == iscol) { 8518 PetscBool stride; 8519 PetscMPIInt grabentirematrix = 0, grab; 8520 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8521 if (stride) { 8522 PetscInt first, step, n, rstart, rend; 8523 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8524 if (step == 1) { 8525 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8526 if (rstart == first) { 8527 PetscCall(ISGetLocalSize(isrow, &n)); 8528 if (n == rend - rstart) grabentirematrix = 1; 8529 } 8530 } 8531 } 8532 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8533 if (grab) { 8534 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8535 if (cll == MAT_INITIAL_MATRIX) { 8536 *newmat = mat; 8537 PetscCall(PetscObjectReference((PetscObject)mat)); 8538 } 8539 PetscFunctionReturn(PETSC_SUCCESS); 8540 } 8541 } 8542 8543 if (!iscol) { 8544 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8545 } else { 8546 iscoltmp = iscol; 8547 } 8548 8549 /* if original matrix is on just one processor then use submatrix generated */ 8550 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8551 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8552 goto setproperties; 8553 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8554 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8555 *newmat = *local; 8556 PetscCall(PetscFree(local)); 8557 goto setproperties; 8558 } else if (!mat->ops->createsubmatrix) { 8559 /* Create a new matrix type that implements the operation using the full matrix */ 8560 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8561 switch (cll) { 8562 case MAT_INITIAL_MATRIX: 8563 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8564 break; 8565 case MAT_REUSE_MATRIX: 8566 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8567 break; 8568 default: 8569 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8570 } 8571 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8572 goto setproperties; 8573 } 8574 8575 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8576 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8577 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8578 8579 setproperties: 8580 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8581 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8582 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8583 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8584 PetscFunctionReturn(PETSC_SUCCESS); 8585 } 8586 8587 /*@ 8588 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8589 8590 Not Collective 8591 8592 Input Parameters: 8593 + A - the matrix we wish to propagate options from 8594 - B - the matrix we wish to propagate options to 8595 8596 Level: beginner 8597 8598 Note: 8599 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8600 8601 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8602 @*/ 8603 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8604 { 8605 PetscFunctionBegin; 8606 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8607 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8608 B->symmetry_eternal = A->symmetry_eternal; 8609 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8610 B->symmetric = A->symmetric; 8611 B->structurally_symmetric = A->structurally_symmetric; 8612 B->spd = A->spd; 8613 B->hermitian = A->hermitian; 8614 PetscFunctionReturn(PETSC_SUCCESS); 8615 } 8616 8617 /*@ 8618 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8619 used during the assembly process to store values that belong to 8620 other processors. 8621 8622 Not Collective 8623 8624 Input Parameters: 8625 + mat - the matrix 8626 . size - the initial size of the stash. 8627 - bsize - the initial size of the block-stash(if used). 8628 8629 Options Database Keys: 8630 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8631 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8632 8633 Level: intermediate 8634 8635 Notes: 8636 The block-stash is used for values set with `MatSetValuesBlocked()` while 8637 the stash is used for values set with `MatSetValues()` 8638 8639 Run with the option -info and look for output of the form 8640 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8641 to determine the appropriate value, MM, to use for size and 8642 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8643 to determine the value, BMM to use for bsize 8644 8645 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8646 @*/ 8647 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8648 { 8649 PetscFunctionBegin; 8650 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8651 PetscValidType(mat, 1); 8652 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8653 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8654 PetscFunctionReturn(PETSC_SUCCESS); 8655 } 8656 8657 /*@ 8658 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8659 the matrix 8660 8661 Neighbor-wise Collective 8662 8663 Input Parameters: 8664 + A - the matrix 8665 . x - the vector to be multiplied by the interpolation operator 8666 - y - the vector to be added to the result 8667 8668 Output Parameter: 8669 . w - the resulting vector 8670 8671 Level: intermediate 8672 8673 Notes: 8674 `w` may be the same vector as `y`. 8675 8676 This allows one to use either the restriction or interpolation (its transpose) 8677 matrix to do the interpolation 8678 8679 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8680 @*/ 8681 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8682 { 8683 PetscInt M, N, Ny; 8684 8685 PetscFunctionBegin; 8686 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8687 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8688 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8689 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8690 PetscCall(MatGetSize(A, &M, &N)); 8691 PetscCall(VecGetSize(y, &Ny)); 8692 if (M == Ny) { 8693 PetscCall(MatMultAdd(A, x, y, w)); 8694 } else { 8695 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8696 } 8697 PetscFunctionReturn(PETSC_SUCCESS); 8698 } 8699 8700 /*@ 8701 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8702 the matrix 8703 8704 Neighbor-wise Collective 8705 8706 Input Parameters: 8707 + A - the matrix 8708 - x - the vector to be interpolated 8709 8710 Output Parameter: 8711 . y - the resulting vector 8712 8713 Level: intermediate 8714 8715 Note: 8716 This allows one to use either the restriction or interpolation (its transpose) 8717 matrix to do the interpolation 8718 8719 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8720 @*/ 8721 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8722 { 8723 PetscInt M, N, Ny; 8724 8725 PetscFunctionBegin; 8726 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8727 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8728 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8729 PetscCall(MatGetSize(A, &M, &N)); 8730 PetscCall(VecGetSize(y, &Ny)); 8731 if (M == Ny) { 8732 PetscCall(MatMult(A, x, y)); 8733 } else { 8734 PetscCall(MatMultTranspose(A, x, y)); 8735 } 8736 PetscFunctionReturn(PETSC_SUCCESS); 8737 } 8738 8739 /*@ 8740 MatRestrict - $y = A*x$ or $A^T*x$ 8741 8742 Neighbor-wise Collective 8743 8744 Input Parameters: 8745 + A - the matrix 8746 - x - the vector to be restricted 8747 8748 Output Parameter: 8749 . y - the resulting vector 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 restriction 8756 8757 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8758 @*/ 8759 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8760 { 8761 PetscInt M, N, Nx; 8762 8763 PetscFunctionBegin; 8764 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8765 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8766 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8767 PetscCall(MatGetSize(A, &M, &N)); 8768 PetscCall(VecGetSize(x, &Nx)); 8769 if (M == Nx) { 8770 PetscCall(MatMultTranspose(A, x, y)); 8771 } else { 8772 PetscCall(MatMult(A, x, y)); 8773 } 8774 PetscFunctionReturn(PETSC_SUCCESS); 8775 } 8776 8777 /*@ 8778 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8779 8780 Neighbor-wise Collective 8781 8782 Input Parameters: 8783 + A - the matrix 8784 . x - the input dense matrix to be multiplied 8785 - w - the input dense matrix to be added to the result 8786 8787 Output Parameter: 8788 . y - the output dense matrix 8789 8790 Level: intermediate 8791 8792 Note: 8793 This allows one to use either the restriction or interpolation (its transpose) 8794 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8795 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8796 8797 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8798 @*/ 8799 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8800 { 8801 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8802 PetscBool trans = PETSC_TRUE; 8803 MatReuse reuse = MAT_INITIAL_MATRIX; 8804 8805 PetscFunctionBegin; 8806 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8807 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8808 PetscValidType(x, 2); 8809 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8810 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8811 PetscCall(MatGetSize(A, &M, &N)); 8812 PetscCall(MatGetSize(x, &Mx, &Nx)); 8813 if (N == Mx) trans = PETSC_FALSE; 8814 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); 8815 Mo = trans ? N : M; 8816 if (*y) { 8817 PetscCall(MatGetSize(*y, &My, &Ny)); 8818 if (Mo == My && Nx == Ny) { 8819 reuse = MAT_REUSE_MATRIX; 8820 } else { 8821 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); 8822 PetscCall(MatDestroy(y)); 8823 } 8824 } 8825 8826 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8827 PetscBool flg; 8828 8829 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8830 if (w) { 8831 PetscInt My, Ny, Mw, Nw; 8832 8833 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8834 PetscCall(MatGetSize(*y, &My, &Ny)); 8835 PetscCall(MatGetSize(w, &Mw, &Nw)); 8836 if (!flg || My != Mw || Ny != Nw) w = NULL; 8837 } 8838 if (!w) { 8839 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8840 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8841 PetscCall(PetscObjectDereference((PetscObject)w)); 8842 } else { 8843 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8844 } 8845 } 8846 if (!trans) { 8847 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8848 } else { 8849 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8850 } 8851 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8852 PetscFunctionReturn(PETSC_SUCCESS); 8853 } 8854 8855 /*@ 8856 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8857 8858 Neighbor-wise Collective 8859 8860 Input Parameters: 8861 + A - the matrix 8862 - x - the input dense matrix 8863 8864 Output Parameter: 8865 . y - the output dense matrix 8866 8867 Level: intermediate 8868 8869 Note: 8870 This allows one to use either the restriction or interpolation (its transpose) 8871 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8872 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8873 8874 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8875 @*/ 8876 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8877 { 8878 PetscFunctionBegin; 8879 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8880 PetscFunctionReturn(PETSC_SUCCESS); 8881 } 8882 8883 /*@ 8884 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8885 8886 Neighbor-wise Collective 8887 8888 Input Parameters: 8889 + A - the matrix 8890 - x - the input dense matrix 8891 8892 Output Parameter: 8893 . y - the output dense matrix 8894 8895 Level: intermediate 8896 8897 Note: 8898 This allows one to use either the restriction or interpolation (its transpose) 8899 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8900 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8901 8902 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8903 @*/ 8904 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8905 { 8906 PetscFunctionBegin; 8907 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8908 PetscFunctionReturn(PETSC_SUCCESS); 8909 } 8910 8911 /*@ 8912 MatGetNullSpace - retrieves the null space of a matrix. 8913 8914 Logically Collective 8915 8916 Input Parameters: 8917 + mat - the matrix 8918 - nullsp - the null space object 8919 8920 Level: developer 8921 8922 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8923 @*/ 8924 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8925 { 8926 PetscFunctionBegin; 8927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8928 PetscAssertPointer(nullsp, 2); 8929 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8930 PetscFunctionReturn(PETSC_SUCCESS); 8931 } 8932 8933 /*@C 8934 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8935 8936 Logically Collective 8937 8938 Input Parameters: 8939 + n - the number of matrices 8940 - mat - the array of matrices 8941 8942 Output Parameters: 8943 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space 8944 8945 Level: developer 8946 8947 Note: 8948 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8949 8950 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8951 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8952 @*/ 8953 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8954 { 8955 PetscFunctionBegin; 8956 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8957 PetscAssertPointer(mat, 2); 8958 PetscAssertPointer(nullsp, 3); 8959 8960 PetscCall(PetscCalloc1(3 * n, nullsp)); 8961 for (PetscInt i = 0; i < n; i++) { 8962 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8963 (*nullsp)[i] = mat[i]->nullsp; 8964 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8965 (*nullsp)[n + i] = mat[i]->nearnullsp; 8966 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8967 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8968 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8969 } 8970 PetscFunctionReturn(PETSC_SUCCESS); 8971 } 8972 8973 /*@C 8974 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8975 8976 Logically Collective 8977 8978 Input Parameters: 8979 + n - the number of matrices 8980 . mat - the array of matrices 8981 - nullsp - an array of null spaces, `NULL` if the null space does not exist 8982 8983 Level: developer 8984 8985 Note: 8986 Call `MatGetNullSpaces()` to create `nullsp` 8987 8988 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8989 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8990 @*/ 8991 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8992 { 8993 PetscFunctionBegin; 8994 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8995 PetscAssertPointer(mat, 2); 8996 PetscAssertPointer(nullsp, 3); 8997 PetscAssertPointer(*nullsp, 3); 8998 8999 for (PetscInt i = 0; i < n; i++) { 9000 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9001 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9002 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9003 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9004 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9005 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9006 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9007 } 9008 PetscCall(PetscFree(*nullsp)); 9009 PetscFunctionReturn(PETSC_SUCCESS); 9010 } 9011 9012 /*@ 9013 MatSetNullSpace - attaches a null space to a matrix. 9014 9015 Logically Collective 9016 9017 Input Parameters: 9018 + mat - the matrix 9019 - nullsp - the null space object 9020 9021 Level: advanced 9022 9023 Notes: 9024 This null space is used by the `KSP` linear solvers to solve singular systems. 9025 9026 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` 9027 9028 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 9029 to zero but the linear system will still be solved in a least squares sense. 9030 9031 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9032 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)$. 9033 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 9034 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 9035 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$). 9036 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9037 9038 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9039 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9040 routine also automatically calls `MatSetTransposeNullSpace()`. 9041 9042 The user should call `MatNullSpaceDestroy()`. 9043 9044 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9045 `KSPSetPCSide()` 9046 @*/ 9047 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9048 { 9049 PetscFunctionBegin; 9050 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9051 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9052 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9053 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9054 mat->nullsp = nullsp; 9055 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9056 PetscFunctionReturn(PETSC_SUCCESS); 9057 } 9058 9059 /*@ 9060 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9061 9062 Logically Collective 9063 9064 Input Parameters: 9065 + mat - the matrix 9066 - nullsp - the null space object 9067 9068 Level: developer 9069 9070 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9071 @*/ 9072 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9073 { 9074 PetscFunctionBegin; 9075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9076 PetscValidType(mat, 1); 9077 PetscAssertPointer(nullsp, 2); 9078 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9079 PetscFunctionReturn(PETSC_SUCCESS); 9080 } 9081 9082 /*@ 9083 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9084 9085 Logically Collective 9086 9087 Input Parameters: 9088 + mat - the matrix 9089 - nullsp - the null space object 9090 9091 Level: advanced 9092 9093 Notes: 9094 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9095 9096 See `MatSetNullSpace()` 9097 9098 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9099 @*/ 9100 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9101 { 9102 PetscFunctionBegin; 9103 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9104 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9105 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9106 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9107 mat->transnullsp = nullsp; 9108 PetscFunctionReturn(PETSC_SUCCESS); 9109 } 9110 9111 /*@ 9112 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9113 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9114 9115 Logically Collective 9116 9117 Input Parameters: 9118 + mat - the matrix 9119 - nullsp - the null space object 9120 9121 Level: advanced 9122 9123 Notes: 9124 Overwrites any previous near null space that may have been attached 9125 9126 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9127 9128 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9129 @*/ 9130 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9131 { 9132 PetscFunctionBegin; 9133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9134 PetscValidType(mat, 1); 9135 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9136 MatCheckPreallocated(mat, 1); 9137 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9138 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9139 mat->nearnullsp = nullsp; 9140 PetscFunctionReturn(PETSC_SUCCESS); 9141 } 9142 9143 /*@ 9144 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9145 9146 Not Collective 9147 9148 Input Parameter: 9149 . mat - the matrix 9150 9151 Output Parameter: 9152 . nullsp - the null space object, `NULL` if not set 9153 9154 Level: advanced 9155 9156 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9157 @*/ 9158 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9159 { 9160 PetscFunctionBegin; 9161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9162 PetscValidType(mat, 1); 9163 PetscAssertPointer(nullsp, 2); 9164 MatCheckPreallocated(mat, 1); 9165 *nullsp = mat->nearnullsp; 9166 PetscFunctionReturn(PETSC_SUCCESS); 9167 } 9168 9169 /*@C 9170 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9171 9172 Collective 9173 9174 Input Parameters: 9175 + mat - the matrix 9176 . row - row/column permutation 9177 - info - information on desired factorization process 9178 9179 Level: developer 9180 9181 Notes: 9182 Probably really in-place only when level of fill is zero, otherwise allocates 9183 new space to store factored matrix and deletes previous memory. 9184 9185 Most users should employ the `KSP` interface for linear solvers 9186 instead of working directly with matrix algebra routines such as this. 9187 See, e.g., `KSPCreate()`. 9188 9189 Developer Note: 9190 The Fortran interface is not autogenerated as the 9191 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9192 9193 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9194 @*/ 9195 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9196 { 9197 PetscFunctionBegin; 9198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9199 PetscValidType(mat, 1); 9200 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9201 PetscAssertPointer(info, 3); 9202 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9203 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9204 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9205 MatCheckPreallocated(mat, 1); 9206 PetscUseTypeMethod(mat, iccfactor, row, info); 9207 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9208 PetscFunctionReturn(PETSC_SUCCESS); 9209 } 9210 9211 /*@ 9212 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9213 ghosted ones. 9214 9215 Not Collective 9216 9217 Input Parameters: 9218 + mat - the matrix 9219 - diag - the diagonal values, including ghost ones 9220 9221 Level: developer 9222 9223 Notes: 9224 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9225 9226 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9227 9228 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9229 @*/ 9230 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9231 { 9232 PetscMPIInt size; 9233 9234 PetscFunctionBegin; 9235 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9236 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9237 PetscValidType(mat, 1); 9238 9239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9240 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9241 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9242 if (size == 1) { 9243 PetscInt n, m; 9244 PetscCall(VecGetSize(diag, &n)); 9245 PetscCall(MatGetSize(mat, NULL, &m)); 9246 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9247 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9248 } else { 9249 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9250 } 9251 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9252 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9253 PetscFunctionReturn(PETSC_SUCCESS); 9254 } 9255 9256 /*@ 9257 MatGetInertia - Gets the inertia from a factored matrix 9258 9259 Collective 9260 9261 Input Parameter: 9262 . mat - the matrix 9263 9264 Output Parameters: 9265 + nneg - number of negative eigenvalues 9266 . nzero - number of zero eigenvalues 9267 - npos - number of positive eigenvalues 9268 9269 Level: advanced 9270 9271 Note: 9272 Matrix must have been factored by `MatCholeskyFactor()` 9273 9274 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9275 @*/ 9276 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9277 { 9278 PetscFunctionBegin; 9279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9280 PetscValidType(mat, 1); 9281 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9282 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9283 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9284 PetscFunctionReturn(PETSC_SUCCESS); 9285 } 9286 9287 /*@C 9288 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9289 9290 Neighbor-wise Collective 9291 9292 Input Parameters: 9293 + mat - the factored matrix obtained with `MatGetFactor()` 9294 - b - the right-hand-side vectors 9295 9296 Output Parameter: 9297 . x - the result vectors 9298 9299 Level: developer 9300 9301 Note: 9302 The vectors `b` and `x` cannot be the same. I.e., one cannot 9303 call `MatSolves`(A,x,x). 9304 9305 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9306 @*/ 9307 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9308 { 9309 PetscFunctionBegin; 9310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9311 PetscValidType(mat, 1); 9312 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9313 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9314 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9315 9316 MatCheckPreallocated(mat, 1); 9317 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9318 PetscUseTypeMethod(mat, solves, b, x); 9319 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9320 PetscFunctionReturn(PETSC_SUCCESS); 9321 } 9322 9323 /*@ 9324 MatIsSymmetric - Test whether a matrix is symmetric 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 transpose) 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 symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9341 9342 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9343 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9344 9345 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9346 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9347 @*/ 9348 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9349 { 9350 PetscFunctionBegin; 9351 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9352 PetscAssertPointer(flg, 3); 9353 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9354 else { 9355 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9356 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9357 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9358 } 9359 PetscFunctionReturn(PETSC_SUCCESS); 9360 } 9361 9362 /*@ 9363 MatIsHermitian - Test whether a matrix is Hermitian 9364 9365 Collective 9366 9367 Input Parameters: 9368 + A - the matrix to test 9369 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9370 9371 Output Parameter: 9372 . flg - the result 9373 9374 Level: intermediate 9375 9376 Notes: 9377 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9378 9379 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9380 9381 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9382 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9383 9384 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9385 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9386 @*/ 9387 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9388 { 9389 PetscFunctionBegin; 9390 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9391 PetscAssertPointer(flg, 3); 9392 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9393 else { 9394 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9395 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9396 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9397 } 9398 PetscFunctionReturn(PETSC_SUCCESS); 9399 } 9400 9401 /*@ 9402 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9403 9404 Not Collective 9405 9406 Input Parameter: 9407 . A - the matrix to check 9408 9409 Output Parameters: 9410 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9411 - flg - the result (only valid if set is `PETSC_TRUE`) 9412 9413 Level: advanced 9414 9415 Notes: 9416 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9417 if you want it explicitly checked 9418 9419 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9420 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9421 9422 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9423 @*/ 9424 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9425 { 9426 PetscFunctionBegin; 9427 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9428 PetscAssertPointer(set, 2); 9429 PetscAssertPointer(flg, 3); 9430 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9431 *set = PETSC_TRUE; 9432 *flg = PetscBool3ToBool(A->symmetric); 9433 } else { 9434 *set = PETSC_FALSE; 9435 } 9436 PetscFunctionReturn(PETSC_SUCCESS); 9437 } 9438 9439 /*@ 9440 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9441 9442 Not Collective 9443 9444 Input Parameter: 9445 . A - the matrix to check 9446 9447 Output Parameters: 9448 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9449 - flg - the result (only valid if set is `PETSC_TRUE`) 9450 9451 Level: advanced 9452 9453 Notes: 9454 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9455 9456 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9457 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9458 9459 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9460 @*/ 9461 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9462 { 9463 PetscFunctionBegin; 9464 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9465 PetscAssertPointer(set, 2); 9466 PetscAssertPointer(flg, 3); 9467 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9468 *set = PETSC_TRUE; 9469 *flg = PetscBool3ToBool(A->spd); 9470 } else { 9471 *set = PETSC_FALSE; 9472 } 9473 PetscFunctionReturn(PETSC_SUCCESS); 9474 } 9475 9476 /*@ 9477 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9478 9479 Not Collective 9480 9481 Input Parameter: 9482 . A - the matrix to check 9483 9484 Output Parameters: 9485 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9486 - flg - the result (only valid if set is `PETSC_TRUE`) 9487 9488 Level: advanced 9489 9490 Notes: 9491 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9492 if you want it explicitly checked 9493 9494 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9495 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9496 9497 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9498 @*/ 9499 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9500 { 9501 PetscFunctionBegin; 9502 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9503 PetscAssertPointer(set, 2); 9504 PetscAssertPointer(flg, 3); 9505 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9506 *set = PETSC_TRUE; 9507 *flg = PetscBool3ToBool(A->hermitian); 9508 } else { 9509 *set = PETSC_FALSE; 9510 } 9511 PetscFunctionReturn(PETSC_SUCCESS); 9512 } 9513 9514 /*@ 9515 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9516 9517 Collective 9518 9519 Input Parameter: 9520 . A - the matrix to test 9521 9522 Output Parameter: 9523 . flg - the result 9524 9525 Level: intermediate 9526 9527 Notes: 9528 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9529 9530 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 9531 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9532 9533 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9534 @*/ 9535 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9536 { 9537 PetscFunctionBegin; 9538 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9539 PetscAssertPointer(flg, 2); 9540 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9541 *flg = PetscBool3ToBool(A->structurally_symmetric); 9542 } else { 9543 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9544 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9545 } 9546 PetscFunctionReturn(PETSC_SUCCESS); 9547 } 9548 9549 /*@ 9550 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9551 9552 Not Collective 9553 9554 Input Parameter: 9555 . A - the matrix to check 9556 9557 Output Parameters: 9558 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9559 - flg - the result (only valid if set is PETSC_TRUE) 9560 9561 Level: advanced 9562 9563 Notes: 9564 One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally 9565 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9566 9567 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9568 9569 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9570 @*/ 9571 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9572 { 9573 PetscFunctionBegin; 9574 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9575 PetscAssertPointer(set, 2); 9576 PetscAssertPointer(flg, 3); 9577 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9578 *set = PETSC_TRUE; 9579 *flg = PetscBool3ToBool(A->structurally_symmetric); 9580 } else { 9581 *set = PETSC_FALSE; 9582 } 9583 PetscFunctionReturn(PETSC_SUCCESS); 9584 } 9585 9586 /*@ 9587 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9588 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9589 9590 Not Collective 9591 9592 Input Parameter: 9593 . mat - the matrix 9594 9595 Output Parameters: 9596 + nstash - the size of the stash 9597 . reallocs - the number of additional mallocs incurred. 9598 . bnstash - the size of the block stash 9599 - breallocs - the number of additional mallocs incurred.in the block stash 9600 9601 Level: advanced 9602 9603 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9604 @*/ 9605 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9606 { 9607 PetscFunctionBegin; 9608 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9609 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9610 PetscFunctionReturn(PETSC_SUCCESS); 9611 } 9612 9613 /*@C 9614 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9615 parallel layout, `PetscLayout` for rows and columns 9616 9617 Collective 9618 9619 Input Parameter: 9620 . mat - the matrix 9621 9622 Output Parameters: 9623 + right - (optional) vector that the matrix can be multiplied against 9624 - left - (optional) vector that the matrix vector product can be stored in 9625 9626 Level: advanced 9627 9628 Notes: 9629 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()`. 9630 9631 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9632 9633 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9634 @*/ 9635 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9636 { 9637 PetscFunctionBegin; 9638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9639 PetscValidType(mat, 1); 9640 if (mat->ops->getvecs) { 9641 PetscUseTypeMethod(mat, getvecs, right, left); 9642 } else { 9643 if (right) { 9644 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9645 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9646 PetscCall(VecSetType(*right, mat->defaultvectype)); 9647 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9648 if (mat->boundtocpu && mat->bindingpropagates) { 9649 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9650 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9651 } 9652 #endif 9653 } 9654 if (left) { 9655 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9656 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9657 PetscCall(VecSetType(*left, mat->defaultvectype)); 9658 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9659 if (mat->boundtocpu && mat->bindingpropagates) { 9660 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9661 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9662 } 9663 #endif 9664 } 9665 } 9666 PetscFunctionReturn(PETSC_SUCCESS); 9667 } 9668 9669 /*@C 9670 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9671 with default values. 9672 9673 Not Collective 9674 9675 Input Parameter: 9676 . info - the `MatFactorInfo` data structure 9677 9678 Level: developer 9679 9680 Notes: 9681 The solvers are generally used through the `KSP` and `PC` objects, for example 9682 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9683 9684 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9685 9686 Developer Note: 9687 The Fortran interface is not autogenerated as the 9688 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9689 9690 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9691 @*/ 9692 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9693 { 9694 PetscFunctionBegin; 9695 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9696 PetscFunctionReturn(PETSC_SUCCESS); 9697 } 9698 9699 /*@ 9700 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9701 9702 Collective 9703 9704 Input Parameters: 9705 + mat - the factored matrix 9706 - is - the index set defining the Schur indices (0-based) 9707 9708 Level: advanced 9709 9710 Notes: 9711 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9712 9713 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9714 9715 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9716 9717 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9718 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9719 @*/ 9720 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9721 { 9722 PetscErrorCode (*f)(Mat, IS); 9723 9724 PetscFunctionBegin; 9725 PetscValidType(mat, 1); 9726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9727 PetscValidType(is, 2); 9728 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9729 PetscCheckSameComm(mat, 1, is, 2); 9730 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9731 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9732 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9733 PetscCall(MatDestroy(&mat->schur)); 9734 PetscCall((*f)(mat, is)); 9735 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9736 PetscFunctionReturn(PETSC_SUCCESS); 9737 } 9738 9739 /*@ 9740 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9741 9742 Logically Collective 9743 9744 Input Parameters: 9745 + F - the factored matrix obtained by calling `MatGetFactor()` 9746 . S - location where to return the Schur complement, can be `NULL` 9747 - status - the status of the Schur complement matrix, can be `NULL` 9748 9749 Level: advanced 9750 9751 Notes: 9752 You must call `MatFactorSetSchurIS()` before calling this routine. 9753 9754 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9755 9756 The routine provides a copy of the Schur matrix stored within the solver data structures. 9757 The caller must destroy the object when it is no longer needed. 9758 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9759 9760 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) 9761 9762 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9763 9764 Developer Note: 9765 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9766 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9767 9768 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9769 @*/ 9770 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9771 { 9772 PetscFunctionBegin; 9773 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9774 if (S) PetscAssertPointer(S, 2); 9775 if (status) PetscAssertPointer(status, 3); 9776 if (S) { 9777 PetscErrorCode (*f)(Mat, Mat *); 9778 9779 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9780 if (f) { 9781 PetscCall((*f)(F, S)); 9782 } else { 9783 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9784 } 9785 } 9786 if (status) *status = F->schur_status; 9787 PetscFunctionReturn(PETSC_SUCCESS); 9788 } 9789 9790 /*@ 9791 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9792 9793 Logically Collective 9794 9795 Input Parameters: 9796 + F - the factored matrix obtained by calling `MatGetFactor()` 9797 . S - location where to return the Schur complement, can be `NULL` 9798 - status - the status of the Schur complement matrix, can be `NULL` 9799 9800 Level: advanced 9801 9802 Notes: 9803 You must call `MatFactorSetSchurIS()` before calling this routine. 9804 9805 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9806 9807 The routine returns a the Schur Complement stored within the data structures of the solver. 9808 9809 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9810 9811 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9812 9813 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9814 9815 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9816 9817 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9818 @*/ 9819 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9820 { 9821 PetscFunctionBegin; 9822 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9823 if (S) { 9824 PetscAssertPointer(S, 2); 9825 *S = F->schur; 9826 } 9827 if (status) { 9828 PetscAssertPointer(status, 3); 9829 *status = F->schur_status; 9830 } 9831 PetscFunctionReturn(PETSC_SUCCESS); 9832 } 9833 9834 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9835 { 9836 Mat S = F->schur; 9837 9838 PetscFunctionBegin; 9839 switch (F->schur_status) { 9840 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9841 case MAT_FACTOR_SCHUR_INVERTED: 9842 if (S) { 9843 S->ops->solve = NULL; 9844 S->ops->matsolve = NULL; 9845 S->ops->solvetranspose = NULL; 9846 S->ops->matsolvetranspose = NULL; 9847 S->ops->solveadd = NULL; 9848 S->ops->solvetransposeadd = NULL; 9849 S->factortype = MAT_FACTOR_NONE; 9850 PetscCall(PetscFree(S->solvertype)); 9851 } 9852 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9853 break; 9854 default: 9855 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9856 } 9857 PetscFunctionReturn(PETSC_SUCCESS); 9858 } 9859 9860 /*@ 9861 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9862 9863 Logically Collective 9864 9865 Input Parameters: 9866 + F - the factored matrix obtained by calling `MatGetFactor()` 9867 . S - location where the Schur complement is stored 9868 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9869 9870 Level: advanced 9871 9872 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9873 @*/ 9874 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9875 { 9876 PetscFunctionBegin; 9877 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9878 if (S) { 9879 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9880 *S = NULL; 9881 } 9882 F->schur_status = status; 9883 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9884 PetscFunctionReturn(PETSC_SUCCESS); 9885 } 9886 9887 /*@ 9888 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9889 9890 Logically Collective 9891 9892 Input Parameters: 9893 + F - the factored matrix obtained by calling `MatGetFactor()` 9894 . rhs - location where the right-hand side of the Schur complement system is stored 9895 - sol - location where the solution of the Schur complement system has to be returned 9896 9897 Level: advanced 9898 9899 Notes: 9900 The sizes of the vectors should match the size of the Schur complement 9901 9902 Must be called after `MatFactorSetSchurIS()` 9903 9904 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9905 @*/ 9906 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9907 { 9908 PetscFunctionBegin; 9909 PetscValidType(F, 1); 9910 PetscValidType(rhs, 2); 9911 PetscValidType(sol, 3); 9912 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9913 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9914 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9915 PetscCheckSameComm(F, 1, rhs, 2); 9916 PetscCheckSameComm(F, 1, sol, 3); 9917 PetscCall(MatFactorFactorizeSchurComplement(F)); 9918 switch (F->schur_status) { 9919 case MAT_FACTOR_SCHUR_FACTORED: 9920 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9921 break; 9922 case MAT_FACTOR_SCHUR_INVERTED: 9923 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9924 break; 9925 default: 9926 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9927 } 9928 PetscFunctionReturn(PETSC_SUCCESS); 9929 } 9930 9931 /*@ 9932 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9933 9934 Logically Collective 9935 9936 Input Parameters: 9937 + F - the factored matrix obtained by calling `MatGetFactor()` 9938 . rhs - location where the right-hand side of the Schur complement system is stored 9939 - sol - location where the solution of the Schur complement system has to be returned 9940 9941 Level: advanced 9942 9943 Notes: 9944 The sizes of the vectors should match the size of the Schur complement 9945 9946 Must be called after `MatFactorSetSchurIS()` 9947 9948 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9949 @*/ 9950 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9951 { 9952 PetscFunctionBegin; 9953 PetscValidType(F, 1); 9954 PetscValidType(rhs, 2); 9955 PetscValidType(sol, 3); 9956 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9957 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9958 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9959 PetscCheckSameComm(F, 1, rhs, 2); 9960 PetscCheckSameComm(F, 1, sol, 3); 9961 PetscCall(MatFactorFactorizeSchurComplement(F)); 9962 switch (F->schur_status) { 9963 case MAT_FACTOR_SCHUR_FACTORED: 9964 PetscCall(MatSolve(F->schur, rhs, sol)); 9965 break; 9966 case MAT_FACTOR_SCHUR_INVERTED: 9967 PetscCall(MatMult(F->schur, rhs, sol)); 9968 break; 9969 default: 9970 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9971 } 9972 PetscFunctionReturn(PETSC_SUCCESS); 9973 } 9974 9975 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9976 #if PetscDefined(HAVE_CUDA) 9977 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9978 #endif 9979 9980 /* Schur status updated in the interface */ 9981 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9982 { 9983 Mat S = F->schur; 9984 9985 PetscFunctionBegin; 9986 if (S) { 9987 PetscMPIInt size; 9988 PetscBool isdense, isdensecuda; 9989 9990 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9991 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9992 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9993 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9994 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9995 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9996 if (isdense) { 9997 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9998 } else if (isdensecuda) { 9999 #if defined(PETSC_HAVE_CUDA) 10000 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10001 #endif 10002 } 10003 // HIP?????????????? 10004 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10005 } 10006 PetscFunctionReturn(PETSC_SUCCESS); 10007 } 10008 10009 /*@ 10010 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10011 10012 Logically Collective 10013 10014 Input Parameter: 10015 . F - the factored matrix obtained by calling `MatGetFactor()` 10016 10017 Level: advanced 10018 10019 Notes: 10020 Must be called after `MatFactorSetSchurIS()`. 10021 10022 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10023 10024 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10025 @*/ 10026 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10027 { 10028 PetscFunctionBegin; 10029 PetscValidType(F, 1); 10030 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10031 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10032 PetscCall(MatFactorFactorizeSchurComplement(F)); 10033 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10034 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10035 PetscFunctionReturn(PETSC_SUCCESS); 10036 } 10037 10038 /*@ 10039 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10040 10041 Logically Collective 10042 10043 Input Parameter: 10044 . F - the factored matrix obtained by calling `MatGetFactor()` 10045 10046 Level: advanced 10047 10048 Note: 10049 Must be called after `MatFactorSetSchurIS()` 10050 10051 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10052 @*/ 10053 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10054 { 10055 MatFactorInfo info; 10056 10057 PetscFunctionBegin; 10058 PetscValidType(F, 1); 10059 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10060 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10061 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10062 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10063 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10064 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10065 } else { 10066 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10067 } 10068 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10069 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10070 PetscFunctionReturn(PETSC_SUCCESS); 10071 } 10072 10073 /*@ 10074 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10075 10076 Neighbor-wise Collective 10077 10078 Input Parameters: 10079 + A - the matrix 10080 . P - the projection matrix 10081 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10082 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10083 if the result is a dense matrix this is irrelevant 10084 10085 Output Parameter: 10086 . C - the product matrix 10087 10088 Level: intermediate 10089 10090 Notes: 10091 C will be created and must be destroyed by the user with `MatDestroy()`. 10092 10093 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10094 10095 Developer Note: 10096 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10097 10098 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10099 @*/ 10100 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10101 { 10102 PetscFunctionBegin; 10103 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10104 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10105 10106 if (scall == MAT_INITIAL_MATRIX) { 10107 PetscCall(MatProductCreate(A, P, NULL, C)); 10108 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10109 PetscCall(MatProductSetAlgorithm(*C, "default")); 10110 PetscCall(MatProductSetFill(*C, fill)); 10111 10112 (*C)->product->api_user = PETSC_TRUE; 10113 PetscCall(MatProductSetFromOptions(*C)); 10114 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); 10115 PetscCall(MatProductSymbolic(*C)); 10116 } else { /* scall == MAT_REUSE_MATRIX */ 10117 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10118 } 10119 10120 PetscCall(MatProductNumeric(*C)); 10121 (*C)->symmetric = A->symmetric; 10122 (*C)->spd = A->spd; 10123 PetscFunctionReturn(PETSC_SUCCESS); 10124 } 10125 10126 /*@ 10127 MatRARt - Creates the matrix product $C = R * A * R^T$ 10128 10129 Neighbor-wise Collective 10130 10131 Input Parameters: 10132 + A - the matrix 10133 . R - the projection matrix 10134 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10135 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10136 if the result is a dense matrix this is irrelevant 10137 10138 Output Parameter: 10139 . C - the product matrix 10140 10141 Level: intermediate 10142 10143 Notes: 10144 C will be created and must be destroyed by the user with `MatDestroy()`. 10145 10146 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10147 10148 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10149 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10150 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10151 We recommend using MatPtAP(). 10152 10153 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10154 @*/ 10155 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10156 { 10157 PetscFunctionBegin; 10158 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10159 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10160 10161 if (scall == MAT_INITIAL_MATRIX) { 10162 PetscCall(MatProductCreate(A, R, NULL, C)); 10163 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10164 PetscCall(MatProductSetAlgorithm(*C, "default")); 10165 PetscCall(MatProductSetFill(*C, fill)); 10166 10167 (*C)->product->api_user = PETSC_TRUE; 10168 PetscCall(MatProductSetFromOptions(*C)); 10169 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); 10170 PetscCall(MatProductSymbolic(*C)); 10171 } else { /* scall == MAT_REUSE_MATRIX */ 10172 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10173 } 10174 10175 PetscCall(MatProductNumeric(*C)); 10176 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10177 PetscFunctionReturn(PETSC_SUCCESS); 10178 } 10179 10180 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10181 { 10182 PetscBool flg = PETSC_TRUE; 10183 10184 PetscFunctionBegin; 10185 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10186 if (scall == MAT_INITIAL_MATRIX) { 10187 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10188 PetscCall(MatProductCreate(A, B, NULL, C)); 10189 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10190 PetscCall(MatProductSetFill(*C, fill)); 10191 } else { /* scall == MAT_REUSE_MATRIX */ 10192 Mat_Product *product = (*C)->product; 10193 10194 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10195 if (flg && product && product->type != ptype) { 10196 PetscCall(MatProductClear(*C)); 10197 product = NULL; 10198 } 10199 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10200 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10201 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10202 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10203 product = (*C)->product; 10204 product->fill = fill; 10205 product->clear = PETSC_TRUE; 10206 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10207 flg = PETSC_FALSE; 10208 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10209 } 10210 } 10211 if (flg) { 10212 (*C)->product->api_user = PETSC_TRUE; 10213 PetscCall(MatProductSetType(*C, ptype)); 10214 PetscCall(MatProductSetFromOptions(*C)); 10215 PetscCall(MatProductSymbolic(*C)); 10216 } 10217 PetscCall(MatProductNumeric(*C)); 10218 PetscFunctionReturn(PETSC_SUCCESS); 10219 } 10220 10221 /*@ 10222 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10223 10224 Neighbor-wise Collective 10225 10226 Input Parameters: 10227 + A - the left matrix 10228 . B - the right matrix 10229 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10230 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10231 if the result is a dense matrix this is irrelevant 10232 10233 Output Parameter: 10234 . C - the product matrix 10235 10236 Notes: 10237 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10238 10239 `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 10240 call to this function with `MAT_INITIAL_MATRIX`. 10241 10242 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10243 10244 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`, 10245 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10246 10247 Example of Usage: 10248 .vb 10249 MatProductCreate(A,B,NULL,&C); 10250 MatProductSetType(C,MATPRODUCT_AB); 10251 MatProductSymbolic(C); 10252 MatProductNumeric(C); // compute C=A * B 10253 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10254 MatProductNumeric(C); 10255 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10256 MatProductNumeric(C); 10257 .ve 10258 10259 Level: intermediate 10260 10261 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10262 @*/ 10263 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10264 { 10265 PetscFunctionBegin; 10266 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10267 PetscFunctionReturn(PETSC_SUCCESS); 10268 } 10269 10270 /*@ 10271 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10272 10273 Neighbor-wise Collective 10274 10275 Input Parameters: 10276 + A - the left matrix 10277 . B - the right matrix 10278 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10279 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10280 10281 Output Parameter: 10282 . C - the product matrix 10283 10284 Options Database Key: 10285 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10286 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10287 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 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 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10297 actually needed. 10298 10299 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10300 and for pairs of `MATMPIDENSE` matrices. 10301 10302 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10303 10304 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10305 @*/ 10306 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10307 { 10308 PetscFunctionBegin; 10309 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10310 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10311 PetscFunctionReturn(PETSC_SUCCESS); 10312 } 10313 10314 /*@ 10315 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10316 10317 Neighbor-wise Collective 10318 10319 Input Parameters: 10320 + A - the left matrix 10321 . B - the right matrix 10322 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10323 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10324 10325 Output Parameter: 10326 . C - the product matrix 10327 10328 Level: intermediate 10329 10330 Notes: 10331 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10332 10333 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10334 10335 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10336 10337 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10338 actually needed. 10339 10340 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10341 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10342 10343 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10344 @*/ 10345 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10346 { 10347 PetscFunctionBegin; 10348 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10349 PetscFunctionReturn(PETSC_SUCCESS); 10350 } 10351 10352 /*@ 10353 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10354 10355 Neighbor-wise Collective 10356 10357 Input Parameters: 10358 + A - the left matrix 10359 . B - the middle matrix 10360 . C - the right matrix 10361 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10362 - 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 10363 if the result is a dense matrix this is irrelevant 10364 10365 Output Parameter: 10366 . D - the product matrix 10367 10368 Level: intermediate 10369 10370 Notes: 10371 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10372 10373 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10374 10375 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10376 10377 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10378 actually needed. 10379 10380 If you have many matrices with the same non-zero structure to multiply, you 10381 should use `MAT_REUSE_MATRIX` in all calls but the first 10382 10383 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10384 @*/ 10385 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10386 { 10387 PetscFunctionBegin; 10388 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10389 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10390 10391 if (scall == MAT_INITIAL_MATRIX) { 10392 PetscCall(MatProductCreate(A, B, C, D)); 10393 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10394 PetscCall(MatProductSetAlgorithm(*D, "default")); 10395 PetscCall(MatProductSetFill(*D, fill)); 10396 10397 (*D)->product->api_user = PETSC_TRUE; 10398 PetscCall(MatProductSetFromOptions(*D)); 10399 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, 10400 ((PetscObject)C)->type_name); 10401 PetscCall(MatProductSymbolic(*D)); 10402 } else { /* user may change input matrices when REUSE */ 10403 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10404 } 10405 PetscCall(MatProductNumeric(*D)); 10406 PetscFunctionReturn(PETSC_SUCCESS); 10407 } 10408 10409 /*@ 10410 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10411 10412 Collective 10413 10414 Input Parameters: 10415 + mat - the matrix 10416 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10417 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10418 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10419 10420 Output Parameter: 10421 . matredundant - redundant matrix 10422 10423 Level: advanced 10424 10425 Notes: 10426 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10427 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10428 10429 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10430 calling it. 10431 10432 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10433 10434 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10435 @*/ 10436 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10437 { 10438 MPI_Comm comm; 10439 PetscMPIInt size; 10440 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10441 Mat_Redundant *redund = NULL; 10442 PetscSubcomm psubcomm = NULL; 10443 MPI_Comm subcomm_in = subcomm; 10444 Mat *matseq; 10445 IS isrow, iscol; 10446 PetscBool newsubcomm = PETSC_FALSE; 10447 10448 PetscFunctionBegin; 10449 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10450 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10451 PetscAssertPointer(*matredundant, 5); 10452 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10453 } 10454 10455 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10456 if (size == 1 || nsubcomm == 1) { 10457 if (reuse == MAT_INITIAL_MATRIX) { 10458 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10459 } else { 10460 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"); 10461 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10462 } 10463 PetscFunctionReturn(PETSC_SUCCESS); 10464 } 10465 10466 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10467 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10468 MatCheckPreallocated(mat, 1); 10469 10470 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10471 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10472 /* create psubcomm, then get subcomm */ 10473 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10474 PetscCallMPI(MPI_Comm_size(comm, &size)); 10475 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10476 10477 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10478 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10479 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10480 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10481 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10482 newsubcomm = PETSC_TRUE; 10483 PetscCall(PetscSubcommDestroy(&psubcomm)); 10484 } 10485 10486 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10487 if (reuse == MAT_INITIAL_MATRIX) { 10488 mloc_sub = PETSC_DECIDE; 10489 nloc_sub = PETSC_DECIDE; 10490 if (bs < 1) { 10491 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10492 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10493 } else { 10494 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10495 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10496 } 10497 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10498 rstart = rend - mloc_sub; 10499 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10500 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10501 PetscCall(ISSetIdentity(iscol)); 10502 } else { /* reuse == MAT_REUSE_MATRIX */ 10503 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"); 10504 /* retrieve subcomm */ 10505 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10506 redund = (*matredundant)->redundant; 10507 isrow = redund->isrow; 10508 iscol = redund->iscol; 10509 matseq = redund->matseq; 10510 } 10511 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10512 10513 /* get matredundant over subcomm */ 10514 if (reuse == MAT_INITIAL_MATRIX) { 10515 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10516 10517 /* create a supporting struct and attach it to C for reuse */ 10518 PetscCall(PetscNew(&redund)); 10519 (*matredundant)->redundant = redund; 10520 redund->isrow = isrow; 10521 redund->iscol = iscol; 10522 redund->matseq = matseq; 10523 if (newsubcomm) { 10524 redund->subcomm = subcomm; 10525 } else { 10526 redund->subcomm = MPI_COMM_NULL; 10527 } 10528 } else { 10529 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10530 } 10531 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10532 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10533 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10534 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10535 } 10536 #endif 10537 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10538 PetscFunctionReturn(PETSC_SUCCESS); 10539 } 10540 10541 /*@C 10542 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10543 a given `Mat`. Each submatrix can span multiple procs. 10544 10545 Collective 10546 10547 Input Parameters: 10548 + mat - the matrix 10549 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10550 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10551 10552 Output Parameter: 10553 . subMat - parallel sub-matrices each spanning a given `subcomm` 10554 10555 Level: advanced 10556 10557 Notes: 10558 The submatrix partition across processors is dictated by `subComm` a 10559 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10560 is not restricted to be grouped with consecutive original MPI processes. 10561 10562 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10563 map directly to the layout of the original matrix [wrt the local 10564 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10565 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10566 the `subMat`. However the offDiagMat looses some columns - and this is 10567 reconstructed with `MatSetValues()` 10568 10569 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10570 10571 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10572 @*/ 10573 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10574 { 10575 PetscMPIInt commsize, subCommSize; 10576 10577 PetscFunctionBegin; 10578 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10579 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10580 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10581 10582 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"); 10583 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10584 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10585 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10586 PetscFunctionReturn(PETSC_SUCCESS); 10587 } 10588 10589 /*@ 10590 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10591 10592 Not Collective 10593 10594 Input Parameters: 10595 + mat - matrix to extract local submatrix from 10596 . isrow - local row indices for submatrix 10597 - iscol - local column indices for submatrix 10598 10599 Output Parameter: 10600 . submat - the submatrix 10601 10602 Level: intermediate 10603 10604 Notes: 10605 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10606 10607 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10608 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10609 10610 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10611 `MatSetValuesBlockedLocal()` will also be implemented. 10612 10613 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10614 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10615 10616 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10617 @*/ 10618 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10619 { 10620 PetscFunctionBegin; 10621 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10622 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10623 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10624 PetscCheckSameComm(isrow, 2, iscol, 3); 10625 PetscAssertPointer(submat, 4); 10626 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10627 10628 if (mat->ops->getlocalsubmatrix) { 10629 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10630 } else { 10631 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10632 } 10633 PetscFunctionReturn(PETSC_SUCCESS); 10634 } 10635 10636 /*@ 10637 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10638 10639 Not Collective 10640 10641 Input Parameters: 10642 + mat - matrix to extract local submatrix from 10643 . isrow - local row indices for submatrix 10644 . iscol - local column indices for submatrix 10645 - submat - the submatrix 10646 10647 Level: intermediate 10648 10649 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10650 @*/ 10651 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10652 { 10653 PetscFunctionBegin; 10654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10655 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10656 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10657 PetscCheckSameComm(isrow, 2, iscol, 3); 10658 PetscAssertPointer(submat, 4); 10659 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10660 10661 if (mat->ops->restorelocalsubmatrix) { 10662 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10663 } else { 10664 PetscCall(MatDestroy(submat)); 10665 } 10666 *submat = NULL; 10667 PetscFunctionReturn(PETSC_SUCCESS); 10668 } 10669 10670 /*@ 10671 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10672 10673 Collective 10674 10675 Input Parameter: 10676 . mat - the matrix 10677 10678 Output Parameter: 10679 . is - if any rows have zero diagonals this contains the list of them 10680 10681 Level: developer 10682 10683 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10684 @*/ 10685 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10686 { 10687 PetscFunctionBegin; 10688 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10689 PetscValidType(mat, 1); 10690 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10691 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10692 10693 if (!mat->ops->findzerodiagonals) { 10694 Vec diag; 10695 const PetscScalar *a; 10696 PetscInt *rows; 10697 PetscInt rStart, rEnd, r, nrow = 0; 10698 10699 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10700 PetscCall(MatGetDiagonal(mat, diag)); 10701 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10702 PetscCall(VecGetArrayRead(diag, &a)); 10703 for (r = 0; r < rEnd - rStart; ++r) 10704 if (a[r] == 0.0) ++nrow; 10705 PetscCall(PetscMalloc1(nrow, &rows)); 10706 nrow = 0; 10707 for (r = 0; r < rEnd - rStart; ++r) 10708 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10709 PetscCall(VecRestoreArrayRead(diag, &a)); 10710 PetscCall(VecDestroy(&diag)); 10711 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10712 } else { 10713 PetscUseTypeMethod(mat, findzerodiagonals, is); 10714 } 10715 PetscFunctionReturn(PETSC_SUCCESS); 10716 } 10717 10718 /*@ 10719 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10720 10721 Collective 10722 10723 Input Parameter: 10724 . mat - the matrix 10725 10726 Output Parameter: 10727 . is - contains the list of rows with off block diagonal entries 10728 10729 Level: developer 10730 10731 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10732 @*/ 10733 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10734 { 10735 PetscFunctionBegin; 10736 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10737 PetscValidType(mat, 1); 10738 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10739 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10740 10741 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10742 PetscFunctionReturn(PETSC_SUCCESS); 10743 } 10744 10745 /*@C 10746 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10747 10748 Collective; No Fortran Support 10749 10750 Input Parameter: 10751 . mat - the matrix 10752 10753 Output Parameter: 10754 . values - the block inverses in column major order (FORTRAN-like) 10755 10756 Level: advanced 10757 10758 Notes: 10759 The size of the blocks is determined by the block size of the matrix. 10760 10761 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10762 10763 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10764 10765 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10766 @*/ 10767 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10768 { 10769 PetscFunctionBegin; 10770 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10771 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10772 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10773 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10774 PetscFunctionReturn(PETSC_SUCCESS); 10775 } 10776 10777 /*@C 10778 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10779 10780 Collective; No Fortran Support 10781 10782 Input Parameters: 10783 + mat - the matrix 10784 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10785 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10786 10787 Output Parameter: 10788 . values - the block inverses in column major order (FORTRAN-like) 10789 10790 Level: advanced 10791 10792 Notes: 10793 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10794 10795 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10796 10797 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10798 @*/ 10799 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10800 { 10801 PetscFunctionBegin; 10802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10803 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10804 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10805 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10806 PetscFunctionReturn(PETSC_SUCCESS); 10807 } 10808 10809 /*@ 10810 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10811 10812 Collective 10813 10814 Input Parameters: 10815 + A - the matrix 10816 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10817 10818 Level: advanced 10819 10820 Note: 10821 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10822 10823 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10824 @*/ 10825 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10826 { 10827 const PetscScalar *vals; 10828 PetscInt *dnnz; 10829 PetscInt m, rstart, rend, bs, i, j; 10830 10831 PetscFunctionBegin; 10832 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10833 PetscCall(MatGetBlockSize(A, &bs)); 10834 PetscCall(MatGetLocalSize(A, &m, NULL)); 10835 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10836 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10837 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10838 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10839 PetscCall(PetscFree(dnnz)); 10840 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10841 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10842 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10843 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10844 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10845 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10846 PetscFunctionReturn(PETSC_SUCCESS); 10847 } 10848 10849 /*@C 10850 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10851 via `MatTransposeColoringCreate()`. 10852 10853 Collective 10854 10855 Input Parameter: 10856 . c - coloring context 10857 10858 Level: intermediate 10859 10860 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10861 @*/ 10862 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10863 { 10864 MatTransposeColoring matcolor = *c; 10865 10866 PetscFunctionBegin; 10867 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10868 if (--((PetscObject)matcolor)->refct > 0) { 10869 matcolor = NULL; 10870 PetscFunctionReturn(PETSC_SUCCESS); 10871 } 10872 10873 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10874 PetscCall(PetscFree(matcolor->rows)); 10875 PetscCall(PetscFree(matcolor->den2sp)); 10876 PetscCall(PetscFree(matcolor->colorforcol)); 10877 PetscCall(PetscFree(matcolor->columns)); 10878 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10879 PetscCall(PetscHeaderDestroy(c)); 10880 PetscFunctionReturn(PETSC_SUCCESS); 10881 } 10882 10883 /*@C 10884 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10885 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10886 `MatTransposeColoring` to sparse `B`. 10887 10888 Collective 10889 10890 Input Parameters: 10891 + coloring - coloring context created with `MatTransposeColoringCreate()` 10892 - B - sparse matrix 10893 10894 Output Parameter: 10895 . Btdense - dense matrix $B^T$ 10896 10897 Level: developer 10898 10899 Note: 10900 These are used internally for some implementations of `MatRARt()` 10901 10902 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10903 @*/ 10904 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10905 { 10906 PetscFunctionBegin; 10907 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10908 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10909 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10910 10911 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10912 PetscFunctionReturn(PETSC_SUCCESS); 10913 } 10914 10915 /*@C 10916 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10917 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10918 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10919 $C_{sp}$ from $C_{den}$. 10920 10921 Collective 10922 10923 Input Parameters: 10924 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10925 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10926 10927 Output Parameter: 10928 . Csp - sparse matrix 10929 10930 Level: developer 10931 10932 Note: 10933 These are used internally for some implementations of `MatRARt()` 10934 10935 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10936 @*/ 10937 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10938 { 10939 PetscFunctionBegin; 10940 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10941 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10942 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10943 10944 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10945 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10946 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10947 PetscFunctionReturn(PETSC_SUCCESS); 10948 } 10949 10950 /*@C 10951 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10952 10953 Collective 10954 10955 Input Parameters: 10956 + mat - the matrix product C 10957 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10958 10959 Output Parameter: 10960 . color - the new coloring context 10961 10962 Level: intermediate 10963 10964 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10965 `MatTransColoringApplyDenToSp()` 10966 @*/ 10967 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10968 { 10969 MatTransposeColoring c; 10970 MPI_Comm comm; 10971 10972 PetscFunctionBegin; 10973 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10974 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10975 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10976 10977 c->ctype = iscoloring->ctype; 10978 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10979 10980 *color = c; 10981 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10982 PetscFunctionReturn(PETSC_SUCCESS); 10983 } 10984 10985 /*@ 10986 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10987 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10988 10989 Not Collective 10990 10991 Input Parameter: 10992 . mat - the matrix 10993 10994 Output Parameter: 10995 . state - the current state 10996 10997 Level: intermediate 10998 10999 Notes: 11000 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11001 different matrices 11002 11003 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11004 11005 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11006 11007 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11008 @*/ 11009 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11010 { 11011 PetscFunctionBegin; 11012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11013 *state = mat->nonzerostate; 11014 PetscFunctionReturn(PETSC_SUCCESS); 11015 } 11016 11017 /*@ 11018 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11019 matrices from each processor 11020 11021 Collective 11022 11023 Input Parameters: 11024 + comm - the communicators the parallel matrix will live on 11025 . seqmat - the input sequential matrices 11026 . n - number of local columns (or `PETSC_DECIDE`) 11027 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11028 11029 Output Parameter: 11030 . mpimat - the parallel matrix generated 11031 11032 Level: developer 11033 11034 Note: 11035 The number of columns of the matrix in EACH processor MUST be the same. 11036 11037 .seealso: [](ch_matrices), `Mat` 11038 @*/ 11039 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11040 { 11041 PetscMPIInt size; 11042 11043 PetscFunctionBegin; 11044 PetscCallMPI(MPI_Comm_size(comm, &size)); 11045 if (size == 1) { 11046 if (reuse == MAT_INITIAL_MATRIX) { 11047 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11048 } else { 11049 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11050 } 11051 PetscFunctionReturn(PETSC_SUCCESS); 11052 } 11053 11054 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"); 11055 11056 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11057 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11058 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11059 PetscFunctionReturn(PETSC_SUCCESS); 11060 } 11061 11062 /*@ 11063 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11064 11065 Collective 11066 11067 Input Parameters: 11068 + A - the matrix to create subdomains from 11069 - N - requested number of subdomains 11070 11071 Output Parameters: 11072 + n - number of subdomains resulting on this MPI process 11073 - iss - `IS` list with indices of subdomains on this MPI process 11074 11075 Level: advanced 11076 11077 Note: 11078 The number of subdomains must be smaller than the communicator size 11079 11080 .seealso: [](ch_matrices), `Mat`, `IS` 11081 @*/ 11082 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11083 { 11084 MPI_Comm comm, subcomm; 11085 PetscMPIInt size, rank, color; 11086 PetscInt rstart, rend, k; 11087 11088 PetscFunctionBegin; 11089 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11090 PetscCallMPI(MPI_Comm_size(comm, &size)); 11091 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11092 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); 11093 *n = 1; 11094 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11095 color = rank / k; 11096 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11097 PetscCall(PetscMalloc1(1, iss)); 11098 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11099 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11100 PetscCallMPI(MPI_Comm_free(&subcomm)); 11101 PetscFunctionReturn(PETSC_SUCCESS); 11102 } 11103 11104 /*@ 11105 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11106 11107 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11108 If they are not the same, uses `MatMatMatMult()`. 11109 11110 Once the coarse grid problem is constructed, correct for interpolation operators 11111 that are not of full rank, which can legitimately happen in the case of non-nested 11112 geometric multigrid. 11113 11114 Input Parameters: 11115 + restrct - restriction operator 11116 . dA - fine grid matrix 11117 . interpolate - interpolation operator 11118 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11119 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11120 11121 Output Parameter: 11122 . A - the Galerkin coarse matrix 11123 11124 Options Database Key: 11125 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11126 11127 Level: developer 11128 11129 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11130 @*/ 11131 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11132 { 11133 IS zerorows; 11134 Vec diag; 11135 11136 PetscFunctionBegin; 11137 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11138 /* Construct the coarse grid matrix */ 11139 if (interpolate == restrct) { 11140 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11141 } else { 11142 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11143 } 11144 11145 /* If the interpolation matrix is not of full rank, A will have zero rows. 11146 This can legitimately happen in the case of non-nested geometric multigrid. 11147 In that event, we set the rows of the matrix to the rows of the identity, 11148 ignoring the equations (as the RHS will also be zero). */ 11149 11150 PetscCall(MatFindZeroRows(*A, &zerorows)); 11151 11152 if (zerorows != NULL) { /* if there are any zero rows */ 11153 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11154 PetscCall(MatGetDiagonal(*A, diag)); 11155 PetscCall(VecISSet(diag, zerorows, 1.0)); 11156 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11157 PetscCall(VecDestroy(&diag)); 11158 PetscCall(ISDestroy(&zerorows)); 11159 } 11160 PetscFunctionReturn(PETSC_SUCCESS); 11161 } 11162 11163 /*@C 11164 MatSetOperation - Allows user to set a matrix operation for any matrix type 11165 11166 Logically Collective 11167 11168 Input Parameters: 11169 + mat - the matrix 11170 . op - the name of the operation 11171 - f - the function that provides the operation 11172 11173 Level: developer 11174 11175 Example Usage: 11176 .vb 11177 extern PetscErrorCode usermult(Mat, Vec, Vec); 11178 11179 PetscCall(MatCreateXXX(comm, ..., &A)); 11180 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11181 .ve 11182 11183 Notes: 11184 See the file `include/petscmat.h` for a complete list of matrix 11185 operations, which all have the form MATOP_<OPERATION>, where 11186 <OPERATION> is the name (in all capital letters) of the 11187 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11188 11189 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11190 sequence as the usual matrix interface routines, since they 11191 are intended to be accessed via the usual matrix interface 11192 routines, e.g., 11193 .vb 11194 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11195 .ve 11196 11197 In particular each function MUST return `PETSC_SUCCESS` on success and 11198 nonzero on failure. 11199 11200 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11201 11202 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11203 @*/ 11204 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11205 { 11206 PetscFunctionBegin; 11207 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11208 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11209 (((void (**)(void))mat->ops)[op]) = f; 11210 PetscFunctionReturn(PETSC_SUCCESS); 11211 } 11212 11213 /*@C 11214 MatGetOperation - Gets a matrix operation for any matrix type. 11215 11216 Not Collective 11217 11218 Input Parameters: 11219 + mat - the matrix 11220 - op - the name of the operation 11221 11222 Output Parameter: 11223 . f - the function that provides the operation 11224 11225 Level: developer 11226 11227 Example Usage: 11228 .vb 11229 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11230 11231 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11232 .ve 11233 11234 Notes: 11235 See the file include/petscmat.h for a complete list of matrix 11236 operations, which all have the form MATOP_<OPERATION>, where 11237 <OPERATION> is the name (in all capital letters) of the 11238 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11239 11240 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11241 11242 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11243 @*/ 11244 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11245 { 11246 PetscFunctionBegin; 11247 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11248 *f = (((void (**)(void))mat->ops)[op]); 11249 PetscFunctionReturn(PETSC_SUCCESS); 11250 } 11251 11252 /*@ 11253 MatHasOperation - Determines whether the given matrix supports the particular operation. 11254 11255 Not Collective 11256 11257 Input Parameters: 11258 + mat - the matrix 11259 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11260 11261 Output Parameter: 11262 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11263 11264 Level: advanced 11265 11266 Note: 11267 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11268 11269 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11270 @*/ 11271 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11272 { 11273 PetscFunctionBegin; 11274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11275 PetscAssertPointer(has, 3); 11276 if (mat->ops->hasoperation) { 11277 PetscUseTypeMethod(mat, hasoperation, op, has); 11278 } else { 11279 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11280 else { 11281 *has = PETSC_FALSE; 11282 if (op == MATOP_CREATE_SUBMATRIX) { 11283 PetscMPIInt size; 11284 11285 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11286 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11287 } 11288 } 11289 } 11290 PetscFunctionReturn(PETSC_SUCCESS); 11291 } 11292 11293 /*@ 11294 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11295 11296 Collective 11297 11298 Input Parameter: 11299 . mat - the matrix 11300 11301 Output Parameter: 11302 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11303 11304 Level: beginner 11305 11306 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11307 @*/ 11308 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11309 { 11310 PetscFunctionBegin; 11311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11312 PetscValidType(mat, 1); 11313 PetscAssertPointer(cong, 2); 11314 if (!mat->rmap || !mat->cmap) { 11315 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11316 PetscFunctionReturn(PETSC_SUCCESS); 11317 } 11318 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11319 PetscCall(PetscLayoutSetUp(mat->rmap)); 11320 PetscCall(PetscLayoutSetUp(mat->cmap)); 11321 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11322 if (*cong) mat->congruentlayouts = 1; 11323 else mat->congruentlayouts = 0; 11324 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11325 PetscFunctionReturn(PETSC_SUCCESS); 11326 } 11327 11328 PetscErrorCode MatSetInf(Mat A) 11329 { 11330 PetscFunctionBegin; 11331 PetscUseTypeMethod(A, setinf); 11332 PetscFunctionReturn(PETSC_SUCCESS); 11333 } 11334 11335 /*@C 11336 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 11337 and possibly removes small values from the graph structure. 11338 11339 Collective 11340 11341 Input Parameters: 11342 + A - the matrix 11343 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11344 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11345 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11346 . num_idx - size of 'index' array 11347 - index - array of block indices to use for graph strength of connection weight 11348 11349 Output Parameter: 11350 . graph - the resulting graph 11351 11352 Level: advanced 11353 11354 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11355 @*/ 11356 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11357 { 11358 PetscFunctionBegin; 11359 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11360 PetscValidType(A, 1); 11361 PetscValidLogicalCollectiveBool(A, scale, 3); 11362 PetscAssertPointer(graph, 7); 11363 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11364 PetscFunctionReturn(PETSC_SUCCESS); 11365 } 11366 11367 /*@ 11368 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11369 meaning the same memory is used for the matrix, and no new memory is allocated. 11370 11371 Collective 11372 11373 Input Parameters: 11374 + A - the matrix 11375 - 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 11376 11377 Level: intermediate 11378 11379 Developer Note: 11380 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11381 of the arrays in the data structure are unneeded. 11382 11383 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11384 @*/ 11385 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11386 { 11387 PetscFunctionBegin; 11388 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11389 PetscUseTypeMethod(A, eliminatezeros, keep); 11390 PetscFunctionReturn(PETSC_SUCCESS); 11391 } 11392