1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n, st; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 207 PetscCall(MatGetSize(mat, &N, NULL)); 208 PetscCall(MatGetLocalSize(mat, &n, NULL)); 209 PetscCall(VecSet(l, 0.0)); 210 PetscCall(VecSetRandom(r, NULL)); 211 PetscCall(MatMult(mat, r, l)); 212 PetscCall(VecGetArrayRead(l, &al)); 213 } else { /* nonzero columns */ 214 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 215 PetscCall(MatGetSize(mat, NULL, &N)); 216 PetscCall(MatGetLocalSize(mat, NULL, &n)); 217 PetscCall(VecSet(r, 0.0)); 218 PetscCall(VecSetRandom(l, NULL)); 219 PetscCall(MatMultTranspose(mat, l, r)); 220 PetscCall(VecGetArrayRead(r, &al)); 221 } 222 if (tol <= 0.0) { 223 for (i = 0, nz = 0; i < n; i++) 224 if (al[i] != 0.0) nz++; 225 } else { 226 for (i = 0, nz = 0; i < n; i++) 227 if (PetscAbsScalar(al[i]) > tol) nz++; 228 } 229 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 230 if (gnz != N) { 231 PetscInt *nzr; 232 PetscCall(PetscMalloc1(nz, &nzr)); 233 if (nz) { 234 if (tol < 0) { 235 for (i = 0, nz = 0; i < n; i++) 236 if (al[i] != 0.0) nzr[nz++] = i + st; 237 } else { 238 for (i = 0, nz = 0; i < n; i++) 239 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 240 } 241 } 242 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 243 } else *nonzero = NULL; 244 if (!cols) { /* nonzero rows */ 245 PetscCall(VecRestoreArrayRead(l, &al)); 246 } else { 247 PetscCall(VecRestoreArrayRead(r, &al)); 248 } 249 PetscCall(VecDestroy(&l)); 250 PetscCall(VecDestroy(&r)); 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 /*@ 255 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 256 257 Input Parameter: 258 . mat - the matrix 259 260 Output Parameter: 261 . keptrows - the rows that are not completely zero 262 263 Level: intermediate 264 265 Note: 266 `keptrows` is set to `NULL` if all rows are nonzero. 267 268 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 269 @*/ 270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 271 { 272 PetscFunctionBegin; 273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 274 PetscValidType(mat, 1); 275 PetscAssertPointer(keptrows, 2); 276 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 277 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 278 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 279 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 280 PetscFunctionReturn(PETSC_SUCCESS); 281 } 282 283 /*@ 284 MatFindZeroRows - Locate all rows that are completely zero in the matrix 285 286 Input Parameter: 287 . mat - the matrix 288 289 Output Parameter: 290 . zerorows - the rows that are completely zero 291 292 Level: intermediate 293 294 Note: 295 `zerorows` is set to `NULL` if no rows are zero. 296 297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 298 @*/ 299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 300 { 301 IS keptrows; 302 PetscInt m, n; 303 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 306 PetscValidType(mat, 1); 307 PetscAssertPointer(zerorows, 2); 308 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 309 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 310 In keeping with this convention, we set zerorows to NULL if there are no zero 311 rows. */ 312 if (keptrows == NULL) { 313 *zerorows = NULL; 314 } else { 315 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 316 PetscCall(ISComplement(keptrows, m, n, zerorows)); 317 PetscCall(ISDestroy(&keptrows)); 318 } 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 324 325 Not Collective 326 327 Input Parameter: 328 . A - the matrix 329 330 Output Parameter: 331 . a - the diagonal part (which is a SEQUENTIAL matrix) 332 333 Level: advanced 334 335 Notes: 336 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 337 338 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 339 340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 341 @*/ 342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 343 { 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 346 PetscValidType(A, 1); 347 PetscAssertPointer(a, 2); 348 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 349 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 350 else { 351 PetscMPIInt size; 352 353 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 354 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 355 *a = A; 356 } 357 PetscFunctionReturn(PETSC_SUCCESS); 358 } 359 360 /*@ 361 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 362 363 Collective 364 365 Input Parameter: 366 . mat - the matrix 367 368 Output Parameter: 369 . trace - the sum of the diagonal entries 370 371 Level: advanced 372 373 .seealso: [](ch_matrices), `Mat` 374 @*/ 375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 376 { 377 Vec diag; 378 379 PetscFunctionBegin; 380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 381 PetscAssertPointer(trace, 2); 382 PetscCall(MatCreateVecs(mat, &diag, NULL)); 383 PetscCall(MatGetDiagonal(mat, diag)); 384 PetscCall(VecSum(diag, trace)); 385 PetscCall(VecDestroy(&diag)); 386 PetscFunctionReturn(PETSC_SUCCESS); 387 } 388 389 /*@ 390 MatRealPart - Zeros out the imaginary part of the matrix 391 392 Logically Collective 393 394 Input Parameter: 395 . mat - the matrix 396 397 Level: advanced 398 399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 400 @*/ 401 PetscErrorCode MatRealPart(Mat mat) 402 { 403 PetscFunctionBegin; 404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 405 PetscValidType(mat, 1); 406 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 407 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 408 MatCheckPreallocated(mat, 1); 409 PetscUseTypeMethod(mat, realpart); 410 PetscFunctionReturn(PETSC_SUCCESS); 411 } 412 413 /*@C 414 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 415 416 Collective 417 418 Input Parameter: 419 . mat - the matrix 420 421 Output Parameters: 422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 423 - ghosts - the global indices of the ghost points 424 425 Level: advanced 426 427 Note: 428 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 429 430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 431 @*/ 432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 433 { 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 436 PetscValidType(mat, 1); 437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 439 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 440 else { 441 if (nghosts) *nghosts = 0; 442 if (ghosts) *ghosts = NULL; 443 } 444 PetscFunctionReturn(PETSC_SUCCESS); 445 } 446 447 /*@ 448 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 449 450 Logically Collective 451 452 Input Parameter: 453 . mat - the matrix 454 455 Level: advanced 456 457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 458 @*/ 459 PetscErrorCode MatImaginaryPart(Mat mat) 460 { 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 463 PetscValidType(mat, 1); 464 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 465 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 466 MatCheckPreallocated(mat, 1); 467 PetscUseTypeMethod(mat, imaginarypart); 468 PetscFunctionReturn(PETSC_SUCCESS); 469 } 470 471 /*@ 472 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 473 474 Not Collective 475 476 Input Parameter: 477 . mat - the matrix 478 479 Output Parameters: 480 + missing - is any diagonal entry missing 481 - dd - first diagonal entry that is missing (optional) on this process 482 483 Level: advanced 484 485 Note: 486 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 487 488 .seealso: [](ch_matrices), `Mat` 489 @*/ 490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 491 { 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 494 PetscValidType(mat, 1); 495 PetscAssertPointer(missing, 2); 496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 498 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 503 /*@C 504 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 505 for each row that you get to ensure that your application does 506 not bleed memory. 507 508 Not Collective 509 510 Input Parameters: 511 + mat - the matrix 512 - row - the row to get 513 514 Output Parameters: 515 + ncols - if not `NULL`, the number of nonzeros in `row` 516 . cols - if not `NULL`, the column numbers 517 - vals - if not `NULL`, the numerical values 518 519 Level: advanced 520 521 Notes: 522 This routine is provided for people who need to have direct access 523 to the structure of a matrix. We hope that we provide enough 524 high-level matrix routines that few users will need it. 525 526 `MatGetRow()` always returns 0-based column indices, regardless of 527 whether the internal representation is 0-based (default) or 1-based. 528 529 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 530 not wish to extract these quantities. 531 532 The user can only examine the values extracted with `MatGetRow()`; 533 the values CANNOT be altered. To change the matrix entries, one 534 must use `MatSetValues()`. 535 536 You can only have one call to `MatGetRow()` outstanding for a particular 537 matrix at a time, per processor. `MatGetRow()` can only obtain rows 538 associated with the given processor, it cannot get rows from the 539 other processors; for that we suggest using `MatCreateSubMatrices()`, then 540 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 541 is in the global number of rows. 542 543 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 544 545 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 546 547 Fortran Note: 548 The calling sequence is 549 .vb 550 MatGetRow(matrix,row,ncols,cols,values,ierr) 551 Mat matrix (input) 552 integer row (input) 553 integer ncols (output) 554 integer cols(maxcols) (output) 555 double precision (or double complex) values(maxcols) output 556 .ve 557 where maxcols >= maximum nonzeros in any row of the matrix. 558 559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 560 @*/ 561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 562 { 563 PetscInt incols; 564 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 567 PetscValidType(mat, 1); 568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 570 MatCheckPreallocated(mat, 1); 571 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 572 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 573 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 574 if (ncols) *ncols = incols; 575 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 576 PetscFunctionReturn(PETSC_SUCCESS); 577 } 578 579 /*@ 580 MatConjugate - replaces the matrix values with their complex conjugates 581 582 Logically Collective 583 584 Input Parameter: 585 . mat - the matrix 586 587 Level: advanced 588 589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 590 @*/ 591 PetscErrorCode MatConjugate(Mat mat) 592 { 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 596 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 597 PetscUseTypeMethod(mat, conjugate); 598 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 599 } 600 PetscFunctionReturn(PETSC_SUCCESS); 601 } 602 603 /*@C 604 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 605 606 Not Collective 607 608 Input Parameters: 609 + mat - the matrix 610 . row - the row to get 611 . ncols - the number of nonzeros 612 . cols - the columns of the nonzeros 613 - vals - if nonzero the column values 614 615 Level: advanced 616 617 Notes: 618 This routine should be called after you have finished examining the entries. 619 620 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 621 us of the array after it has been restored. If you pass `NULL`, it will 622 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 623 624 Fortran Notes: 625 The calling sequence is 626 .vb 627 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 628 Mat matrix (input) 629 integer row (input) 630 integer ncols (output) 631 integer cols(maxcols) (output) 632 double precision (or double complex) values(maxcols) output 633 .ve 634 Where maxcols >= maximum nonzeros in any row of the matrix. 635 636 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 637 before another call to `MatGetRow()` can be made. 638 639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 640 @*/ 641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 642 { 643 PetscFunctionBegin; 644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 645 if (ncols) PetscAssertPointer(ncols, 3); 646 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 647 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 648 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 649 if (ncols) *ncols = 0; 650 if (cols) *cols = NULL; 651 if (vals) *vals = NULL; 652 PetscFunctionReturn(PETSC_SUCCESS); 653 } 654 655 /*@ 656 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 657 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 658 659 Not Collective 660 661 Input Parameter: 662 . mat - the matrix 663 664 Level: advanced 665 666 Note: 667 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 668 669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 670 @*/ 671 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 672 { 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 675 PetscValidType(mat, 1); 676 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 677 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 678 MatCheckPreallocated(mat, 1); 679 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 680 PetscUseTypeMethod(mat, getrowuppertriangular); 681 PetscFunctionReturn(PETSC_SUCCESS); 682 } 683 684 /*@ 685 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 686 687 Not Collective 688 689 Input Parameter: 690 . mat - the matrix 691 692 Level: advanced 693 694 Note: 695 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 696 697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 698 @*/ 699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 700 { 701 PetscFunctionBegin; 702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 703 PetscValidType(mat, 1); 704 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 705 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 706 MatCheckPreallocated(mat, 1); 707 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 708 PetscUseTypeMethod(mat, restorerowuppertriangular); 709 PetscFunctionReturn(PETSC_SUCCESS); 710 } 711 712 /*@C 713 MatSetOptionsPrefix - Sets the prefix used for searching for all 714 `Mat` options in the database. 715 716 Logically Collective 717 718 Input Parameters: 719 + A - the matrix 720 - prefix - the prefix to prepend to all option names 721 722 Level: advanced 723 724 Notes: 725 A hyphen (-) must NOT be given at the beginning of the prefix name. 726 The first character of all runtime options is AUTOMATICALLY the hyphen. 727 728 This is NOT used for options for the factorization of the matrix. Normally the 729 prefix is automatically passed in from the PC calling the factorization. To set 730 it directly use `MatSetOptionsPrefixFactor()` 731 732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 733 @*/ 734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 735 { 736 PetscFunctionBegin; 737 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 738 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 739 PetscFunctionReturn(PETSC_SUCCESS); 740 } 741 742 /*@C 743 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 744 for matrices created with `MatGetFactor()` 745 746 Logically Collective 747 748 Input Parameters: 749 + A - the matrix 750 - prefix - the prefix to prepend to all option names for the factored matrix 751 752 Level: developer 753 754 Notes: 755 A hyphen (-) must NOT be given at the beginning of the prefix name. 756 The first character of all runtime options is AUTOMATICALLY the hyphen. 757 758 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 759 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 760 761 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 762 @*/ 763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 764 { 765 PetscFunctionBegin; 766 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 767 if (prefix) { 768 PetscAssertPointer(prefix, 2); 769 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 770 if (prefix != A->factorprefix) { 771 PetscCall(PetscFree(A->factorprefix)); 772 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 773 } 774 } else PetscCall(PetscFree(A->factorprefix)); 775 PetscFunctionReturn(PETSC_SUCCESS); 776 } 777 778 /*@C 779 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 780 for matrices created with `MatGetFactor()` 781 782 Logically Collective 783 784 Input Parameters: 785 + A - the matrix 786 - prefix - the prefix to prepend to all option names for the factored matrix 787 788 Level: developer 789 790 Notes: 791 A hyphen (-) must NOT be given at the beginning of the prefix name. 792 The first character of all runtime options is AUTOMATICALLY the hyphen. 793 794 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 795 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 796 797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 798 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 799 `MatSetOptionsPrefix()` 800 @*/ 801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 802 { 803 size_t len1, len2, new_len; 804 805 PetscFunctionBegin; 806 PetscValidHeader(A, 1); 807 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 808 if (!A->factorprefix) { 809 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 810 PetscFunctionReturn(PETSC_SUCCESS); 811 } 812 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 813 814 PetscCall(PetscStrlen(A->factorprefix, &len1)); 815 PetscCall(PetscStrlen(prefix, &len2)); 816 new_len = len1 + len2 + 1; 817 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 818 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 819 PetscFunctionReturn(PETSC_SUCCESS); 820 } 821 822 /*@C 823 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 824 matrix options in the database. 825 826 Logically Collective 827 828 Input Parameters: 829 + A - the matrix 830 - prefix - the prefix to prepend to all option names 831 832 Level: advanced 833 834 Note: 835 A hyphen (-) must NOT be given at the beginning of the prefix name. 836 The first character of all runtime options is AUTOMATICALLY the hyphen. 837 838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 839 @*/ 840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 844 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 845 PetscFunctionReturn(PETSC_SUCCESS); 846 } 847 848 /*@C 849 MatGetOptionsPrefix - Gets the prefix used for searching for all 850 matrix options in the database. 851 852 Not Collective 853 854 Input Parameter: 855 . A - the matrix 856 857 Output Parameter: 858 . prefix - pointer to the prefix string used 859 860 Level: advanced 861 862 Fortran Note: 863 The user should pass in a string `prefix` of 864 sufficient length to hold the prefix. 865 866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 867 @*/ 868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 869 { 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 872 PetscAssertPointer(prefix, 2); 873 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 874 PetscFunctionReturn(PETSC_SUCCESS); 875 } 876 877 /*@ 878 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 879 880 Collective 881 882 Input Parameter: 883 . A - the matrix 884 885 Level: beginner 886 887 Notes: 888 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 889 890 Users can reset the preallocation to access the original memory. 891 892 Currently only supported for `MATAIJ` matrices. 893 894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 895 @*/ 896 PetscErrorCode MatResetPreallocation(Mat A) 897 { 898 PetscFunctionBegin; 899 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 900 PetscValidType(A, 1); 901 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 902 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 903 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 904 PetscFunctionReturn(PETSC_SUCCESS); 905 } 906 907 /*@ 908 MatSetUp - Sets up the internal matrix data structures for later use. 909 910 Collective 911 912 Input Parameter: 913 . A - the matrix 914 915 Level: intermediate 916 917 Notes: 918 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 919 setting values in the matrix. 920 921 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 922 923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 924 @*/ 925 PetscErrorCode MatSetUp(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 if (!((PetscObject)A)->type_name) { 930 PetscMPIInt size; 931 932 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 933 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 934 } 935 if (!A->preallocated) PetscTryTypeMethod(A, setup); 936 PetscCall(PetscLayoutSetUp(A->rmap)); 937 PetscCall(PetscLayoutSetUp(A->cmap)); 938 A->preallocated = PETSC_TRUE; 939 PetscFunctionReturn(PETSC_SUCCESS); 940 } 941 942 #if defined(PETSC_HAVE_SAWS) 943 #include <petscviewersaws.h> 944 #endif 945 946 /* 947 If threadsafety is on extraneous matrices may be printed 948 949 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 950 */ 951 #if !defined(PETSC_HAVE_THREADSAFETY) 952 static PetscInt insidematview = 0; 953 #endif 954 955 /*@C 956 MatViewFromOptions - View properties of the matrix based on options set in the options database 957 958 Collective 959 960 Input Parameters: 961 + A - the matrix 962 . obj - optional additional object that provides the options prefix to use 963 - name - command line option 964 965 Options Database Key: 966 . -mat_view [viewertype]:... - the viewer and its options 967 968 Level: intermediate 969 970 Note: 971 .vb 972 If no value is provided ascii:stdout is used 973 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 974 for example ascii::ascii_info prints just the information about the object not all details 975 unless :append is given filename opens in write mode, overwriting what was already there 976 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 977 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 978 socket[:port] defaults to the standard output port 979 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 980 .ve 981 982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 983 @*/ 984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 985 { 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 988 #if !defined(PETSC_HAVE_THREADSAFETY) 989 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 990 #endif 991 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 992 PetscFunctionReturn(PETSC_SUCCESS); 993 } 994 995 /*@C 996 MatView - display information about a matrix in a variety ways 997 998 Collective 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 PetscCheckSameComm(mat, 1, viewer, 2); 1087 1088 PetscCall(PetscViewerGetFormat(viewer, &format)); 1089 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1090 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1091 1092 #if !defined(PETSC_HAVE_THREADSAFETY) 1093 insidematview++; 1094 #endif 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1097 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1098 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1099 1100 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1101 if (isascii) { 1102 if (!mat->preallocated) { 1103 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1104 #if !defined(PETSC_HAVE_THREADSAFETY) 1105 insidematview--; 1106 #endif 1107 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1108 PetscFunctionReturn(PETSC_SUCCESS); 1109 } 1110 if (!mat->assembled) { 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1112 #if !defined(PETSC_HAVE_THREADSAFETY) 1113 insidematview--; 1114 #endif 1115 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1116 PetscFunctionReturn(PETSC_SUCCESS); 1117 } 1118 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1119 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1120 MatNullSpace nullsp, transnullsp; 1121 1122 PetscCall(PetscViewerASCIIPushTab(viewer)); 1123 PetscCall(MatGetSize(mat, &rows, &cols)); 1124 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1125 if (rbs != 1 || cbs != 1) { 1126 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" : "")); 1127 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1128 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1129 if (mat->factortype) { 1130 MatSolverType solver; 1131 PetscCall(MatFactorGetSolverType(mat, &solver)); 1132 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1133 } 1134 if (mat->ops->getinfo) { 1135 MatInfo info; 1136 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1137 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1138 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1139 } 1140 PetscCall(MatGetNullSpace(mat, &nullsp)); 1141 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1142 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1143 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1144 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1145 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscCall(MatProductView(mat, viewer)); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1150 IS tmp; 1151 1152 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1153 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1154 PetscCall(PetscViewerASCIIPushTab(viewer)); 1155 PetscCall(ISView(tmp, viewer)); 1156 PetscCall(PetscViewerASCIIPopTab(viewer)); 1157 PetscCall(ISDestroy(&tmp)); 1158 } 1159 } 1160 } else if (issaws) { 1161 #if defined(PETSC_HAVE_SAWS) 1162 PetscMPIInt rank; 1163 1164 PetscCall(PetscObjectName((PetscObject)mat)); 1165 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1166 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1167 #endif 1168 } else if (isstring) { 1169 const char *type; 1170 PetscCall(MatGetType(mat, &type)); 1171 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1172 PetscTryTypeMethod(mat, view, viewer); 1173 } 1174 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1175 PetscCall(PetscViewerASCIIPushTab(viewer)); 1176 PetscUseTypeMethod(mat, viewnative, viewer); 1177 PetscCall(PetscViewerASCIIPopTab(viewer)); 1178 } else if (mat->ops->view) { 1179 PetscCall(PetscViewerASCIIPushTab(viewer)); 1180 PetscUseTypeMethod(mat, view, viewer); 1181 PetscCall(PetscViewerASCIIPopTab(viewer)); 1182 } 1183 if (isascii) { 1184 PetscCall(PetscViewerGetFormat(viewer, &format)); 1185 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1186 } 1187 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1188 #if !defined(PETSC_HAVE_THREADSAFETY) 1189 insidematview--; 1190 #endif 1191 PetscFunctionReturn(PETSC_SUCCESS); 1192 } 1193 1194 #if defined(PETSC_USE_DEBUG) 1195 #include <../src/sys/totalview/tv_data_display.h> 1196 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1197 { 1198 TV_add_row("Local rows", "int", &mat->rmap->n); 1199 TV_add_row("Local columns", "int", &mat->cmap->n); 1200 TV_add_row("Global rows", "int", &mat->rmap->N); 1201 TV_add_row("Global columns", "int", &mat->cmap->N); 1202 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1203 return TV_format_OK; 1204 } 1205 #endif 1206 1207 /*@C 1208 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1209 with `MatView()`. The matrix format is determined from the options database. 1210 Generates a parallel MPI matrix if the communicator has more than one 1211 processor. The default matrix type is `MATAIJ`. 1212 1213 Collective 1214 1215 Input Parameters: 1216 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1217 or some related function before a call to `MatLoad()` 1218 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1219 1220 Options Database Key: 1221 . -matload_block_size <bs> - set block size 1222 1223 Level: beginner 1224 1225 Notes: 1226 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1227 `Mat` before calling this routine if you wish to set it from the options database. 1228 1229 `MatLoad()` automatically loads into the options database any options 1230 given in the file filename.info where filename is the name of the file 1231 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1232 file will be ignored if you use the -viewer_binary_skip_info option. 1233 1234 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1235 sets the default matrix type AIJ and sets the local and global sizes. 1236 If type and/or size is already set, then the same are used. 1237 1238 In parallel, each processor can load a subset of rows (or the 1239 entire matrix). This routine is especially useful when a large 1240 matrix is stored on disk and only part of it is desired on each 1241 processor. For example, a parallel solver may access only some of 1242 the rows from each processor. The algorithm used here reads 1243 relatively small blocks of data rather than reading the entire 1244 matrix and then subsetting it. 1245 1246 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1247 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1248 or the sequence like 1249 .vb 1250 `PetscViewer` v; 1251 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1252 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1253 `PetscViewerSetFromOptions`(v); 1254 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1255 `PetscViewerFileSetName`(v,"datafile"); 1256 .ve 1257 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1258 $ -viewer_type {binary, hdf5} 1259 1260 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1261 and src/mat/tutorials/ex10.c with the second approach. 1262 1263 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1264 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1265 Multiple objects, both matrices and vectors, can be stored within the same file. 1266 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1267 1268 Most users should not need to know the details of the binary storage 1269 format, since `MatLoad()` and `MatView()` completely hide these details. 1270 But for anyone who is interested, the standard binary matrix storage 1271 format is 1272 1273 .vb 1274 PetscInt MAT_FILE_CLASSID 1275 PetscInt number of rows 1276 PetscInt number of columns 1277 PetscInt total number of nonzeros 1278 PetscInt *number nonzeros in each row 1279 PetscInt *column indices of all nonzeros (starting index is zero) 1280 PetscScalar *values of all nonzeros 1281 .ve 1282 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1283 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 1284 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1285 1286 PETSc automatically does the byte swapping for 1287 machines that store the bytes reversed. Thus if you write your own binary 1288 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1289 and `PetscBinaryWrite()` to see how this may be done. 1290 1291 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1292 Each processor's chunk is loaded independently by its owning MPI process. 1293 Multiple objects, both matrices and vectors, can be stored within the same file. 1294 They are looked up by their PetscObject name. 1295 1296 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1297 by default the same structure and naming of the AIJ arrays and column count 1298 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1299 $ save example.mat A b -v7.3 1300 can be directly read by this routine (see Reference 1 for details). 1301 1302 Depending on your MATLAB version, this format might be a default, 1303 otherwise you can set it as default in Preferences. 1304 1305 Unless -nocompression flag is used to save the file in MATLAB, 1306 PETSc must be configured with ZLIB package. 1307 1308 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1309 1310 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1311 1312 Corresponding `MatView()` is not yet implemented. 1313 1314 The loaded matrix is actually a transpose of the original one in MATLAB, 1315 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1316 With this format, matrix is automatically transposed by PETSc, 1317 unless the matrix is marked as SPD or symmetric 1318 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1319 1320 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1321 1322 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1323 @*/ 1324 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1325 { 1326 PetscBool flg; 1327 1328 PetscFunctionBegin; 1329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1330 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1331 1332 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1333 1334 flg = PETSC_FALSE; 1335 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1336 if (flg) { 1337 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1338 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1339 } 1340 flg = PETSC_FALSE; 1341 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1342 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1343 1344 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1345 PetscUseTypeMethod(mat, load, viewer); 1346 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1347 PetscFunctionReturn(PETSC_SUCCESS); 1348 } 1349 1350 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1351 { 1352 Mat_Redundant *redund = *redundant; 1353 1354 PetscFunctionBegin; 1355 if (redund) { 1356 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1357 PetscCall(ISDestroy(&redund->isrow)); 1358 PetscCall(ISDestroy(&redund->iscol)); 1359 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1360 } else { 1361 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1362 PetscCall(PetscFree(redund->sbuf_j)); 1363 PetscCall(PetscFree(redund->sbuf_a)); 1364 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1365 PetscCall(PetscFree(redund->rbuf_j[i])); 1366 PetscCall(PetscFree(redund->rbuf_a[i])); 1367 } 1368 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1369 } 1370 1371 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1372 PetscCall(PetscFree(redund)); 1373 } 1374 PetscFunctionReturn(PETSC_SUCCESS); 1375 } 1376 1377 /*@C 1378 MatDestroy - Frees space taken by a matrix. 1379 1380 Collective 1381 1382 Input Parameter: 1383 . A - the matrix 1384 1385 Level: beginner 1386 1387 Developer Note: 1388 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1389 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1390 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1391 if changes are needed here. 1392 1393 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1394 @*/ 1395 PetscErrorCode MatDestroy(Mat *A) 1396 { 1397 PetscFunctionBegin; 1398 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1399 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1400 if (--((PetscObject)*A)->refct > 0) { 1401 *A = NULL; 1402 PetscFunctionReturn(PETSC_SUCCESS); 1403 } 1404 1405 /* if memory was published with SAWs then destroy it */ 1406 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1407 PetscTryTypeMethod(*A, destroy); 1408 1409 PetscCall(PetscFree((*A)->factorprefix)); 1410 PetscCall(PetscFree((*A)->defaultvectype)); 1411 PetscCall(PetscFree((*A)->defaultrandtype)); 1412 PetscCall(PetscFree((*A)->bsizes)); 1413 PetscCall(PetscFree((*A)->solvertype)); 1414 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1415 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1416 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1417 PetscCall(MatProductClear(*A)); 1418 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1419 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1420 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1421 PetscCall(MatDestroy(&(*A)->schur)); 1422 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1423 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1424 PetscCall(PetscHeaderDestroy(A)); 1425 PetscFunctionReturn(PETSC_SUCCESS); 1426 } 1427 1428 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1429 /*@C 1430 MatSetValues - Inserts or adds a block of values into a matrix. 1431 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1432 MUST be called after all calls to `MatSetValues()` have been completed. 1433 1434 Not Collective 1435 1436 Input Parameters: 1437 + mat - the matrix 1438 . v - a logically two-dimensional array of values 1439 . m - the number of rows 1440 . idxm - the global indices of the rows 1441 . n - the number of columns 1442 . idxn - the global indices of the columns 1443 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1444 1445 Level: beginner 1446 1447 Notes: 1448 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1449 1450 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1451 options cannot be mixed without intervening calls to the assembly 1452 routines. 1453 1454 `MatSetValues()` uses 0-based row and column numbers in Fortran 1455 as well as in C. 1456 1457 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1458 simply ignored. This allows easily inserting element stiffness matrices 1459 with homogeneous Dirichlet boundary conditions that you don't want represented 1460 in the matrix. 1461 1462 Efficiency Alert: 1463 The routine `MatSetValuesBlocked()` may offer much better efficiency 1464 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1465 1466 Developer Note: 1467 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1468 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1469 1470 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1471 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1472 @*/ 1473 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1474 { 1475 PetscFunctionBeginHot; 1476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1477 PetscValidType(mat, 1); 1478 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1479 PetscAssertPointer(idxm, 3); 1480 PetscAssertPointer(idxn, 5); 1481 MatCheckPreallocated(mat, 1); 1482 1483 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1484 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1485 1486 if (PetscDefined(USE_DEBUG)) { 1487 PetscInt i, j; 1488 1489 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 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 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); 1501 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); 1502 } 1503 1504 if (mat->assembled) { 1505 mat->was_assembled = PETSC_TRUE; 1506 mat->assembled = PETSC_FALSE; 1507 } 1508 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1509 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1510 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1511 PetscFunctionReturn(PETSC_SUCCESS); 1512 } 1513 1514 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1515 /*@C 1516 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1517 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1518 MUST be called after all calls to `MatSetValues()` have been completed. 1519 1520 Not Collective 1521 1522 Input Parameters: 1523 + mat - the matrix 1524 . v - a logically two-dimensional array of values 1525 . ism - the rows to provide 1526 . isn - the columns to provide 1527 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1528 1529 Level: beginner 1530 1531 Notes: 1532 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1533 1534 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1535 options cannot be mixed without intervening calls to the assembly 1536 routines. 1537 1538 `MatSetValues()` uses 0-based row and column numbers in Fortran 1539 as well as in C. 1540 1541 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1542 simply ignored. This allows easily inserting element stiffness matrices 1543 with homogeneous Dirichlet boundary conditions that you don't want represented 1544 in the matrix. 1545 1546 Efficiency Alert: 1547 The routine `MatSetValuesBlocked()` may offer much better efficiency 1548 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1549 1550 This is currently not optimized for any particular `ISType` 1551 1552 Developer Note: 1553 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1554 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1555 1556 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1557 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1558 @*/ 1559 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1560 { 1561 PetscInt m, n; 1562 const PetscInt *rows, *cols; 1563 1564 PetscFunctionBeginHot; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscCall(ISGetIndices(ism, &rows)); 1567 PetscCall(ISGetIndices(isn, &cols)); 1568 PetscCall(ISGetLocalSize(ism, &m)); 1569 PetscCall(ISGetLocalSize(isn, &n)); 1570 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1571 PetscCall(ISRestoreIndices(ism, &rows)); 1572 PetscCall(ISRestoreIndices(isn, &cols)); 1573 PetscFunctionReturn(PETSC_SUCCESS); 1574 } 1575 1576 /*@ 1577 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1578 values into a matrix 1579 1580 Not Collective 1581 1582 Input Parameters: 1583 + mat - the matrix 1584 . row - the (block) row to set 1585 - v - a logically two-dimensional array of values 1586 1587 Level: intermediate 1588 1589 Notes: 1590 The values, `v`, are column-oriented (for the block version) and sorted 1591 1592 All the nonzero values in `row` must be provided 1593 1594 The matrix must have previously had its column indices set, likely by having been assembled. 1595 1596 `row` must belong to this MPI process 1597 1598 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1599 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1600 @*/ 1601 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1602 { 1603 PetscInt globalrow; 1604 1605 PetscFunctionBegin; 1606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1607 PetscValidType(mat, 1); 1608 PetscAssertPointer(v, 3); 1609 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1610 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1611 PetscFunctionReturn(PETSC_SUCCESS); 1612 } 1613 1614 /*@ 1615 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1616 values into a matrix 1617 1618 Not Collective 1619 1620 Input Parameters: 1621 + mat - the matrix 1622 . row - the (block) row to set 1623 - 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 1624 1625 Level: advanced 1626 1627 Notes: 1628 The values, `v`, are column-oriented for the block version. 1629 1630 All the nonzeros in `row` must be provided 1631 1632 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1633 1634 `row` must belong to this process 1635 1636 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1637 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1638 @*/ 1639 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1640 { 1641 PetscFunctionBeginHot; 1642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1643 PetscValidType(mat, 1); 1644 MatCheckPreallocated(mat, 1); 1645 PetscAssertPointer(v, 3); 1646 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1647 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1648 mat->insertmode = INSERT_VALUES; 1649 1650 if (mat->assembled) { 1651 mat->was_assembled = PETSC_TRUE; 1652 mat->assembled = PETSC_FALSE; 1653 } 1654 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1655 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1656 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1657 PetscFunctionReturn(PETSC_SUCCESS); 1658 } 1659 1660 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1661 /*@ 1662 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1663 Using structured grid indexing 1664 1665 Not Collective 1666 1667 Input Parameters: 1668 + mat - the matrix 1669 . m - number of rows being entered 1670 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1671 . n - number of columns being entered 1672 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1673 . v - a logically two-dimensional array of values 1674 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1675 1676 Level: beginner 1677 1678 Notes: 1679 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1680 1681 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1682 options cannot be mixed without intervening calls to the assembly 1683 routines. 1684 1685 The grid coordinates are across the entire grid, not just the local portion 1686 1687 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1688 as well as in C. 1689 1690 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1691 1692 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1693 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1694 1695 The columns and rows in the stencil passed in MUST be contained within the 1696 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1697 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1698 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1699 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1700 1701 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1702 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1703 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1704 `DM_BOUNDARY_PERIODIC` boundary type. 1705 1706 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 1707 a single value per point) you can skip filling those indices. 1708 1709 Inspired by the structured grid interface to the HYPRE package 1710 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1711 1712 Efficiency Alert: 1713 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1714 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1715 1716 Fortran Note: 1717 `idxm` and `idxn` should be declared as 1718 $ MatStencil idxm(4,m),idxn(4,n) 1719 and the values inserted using 1720 .vb 1721 idxm(MatStencil_i,1) = i 1722 idxm(MatStencil_j,1) = j 1723 idxm(MatStencil_k,1) = k 1724 idxm(MatStencil_c,1) = c 1725 etc 1726 .ve 1727 1728 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1729 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1730 @*/ 1731 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1732 { 1733 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1734 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1735 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1736 1737 PetscFunctionBegin; 1738 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1739 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1740 PetscValidType(mat, 1); 1741 PetscAssertPointer(idxm, 3); 1742 PetscAssertPointer(idxn, 5); 1743 1744 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1745 jdxm = buf; 1746 jdxn = buf + m; 1747 } else { 1748 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1749 jdxm = bufm; 1750 jdxn = bufn; 1751 } 1752 for (i = 0; i < m; i++) { 1753 for (j = 0; j < 3 - sdim; j++) dxm++; 1754 tmp = *dxm++ - starts[0]; 1755 for (j = 0; j < dim - 1; j++) { 1756 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1757 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1758 } 1759 if (mat->stencil.noc) dxm++; 1760 jdxm[i] = tmp; 1761 } 1762 for (i = 0; i < n; i++) { 1763 for (j = 0; j < 3 - sdim; j++) dxn++; 1764 tmp = *dxn++ - starts[0]; 1765 for (j = 0; j < dim - 1; j++) { 1766 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1767 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1768 } 1769 if (mat->stencil.noc) dxn++; 1770 jdxn[i] = tmp; 1771 } 1772 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1773 PetscCall(PetscFree2(bufm, bufn)); 1774 PetscFunctionReturn(PETSC_SUCCESS); 1775 } 1776 1777 /*@ 1778 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1779 Using structured grid indexing 1780 1781 Not Collective 1782 1783 Input Parameters: 1784 + mat - the matrix 1785 . m - number of rows being entered 1786 . idxm - grid coordinates for matrix rows being entered 1787 . n - number of columns being entered 1788 . idxn - grid coordinates for matrix columns being entered 1789 . v - a logically two-dimensional array of values 1790 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1791 1792 Level: beginner 1793 1794 Notes: 1795 By default the values, `v`, are row-oriented and unsorted. 1796 See `MatSetOption()` for other options. 1797 1798 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1799 options cannot be mixed without intervening calls to the assembly 1800 routines. 1801 1802 The grid coordinates are across the entire grid, not just the local portion 1803 1804 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1805 as well as in C. 1806 1807 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1808 1809 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1810 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1811 1812 The columns and rows in the stencil passed in MUST be contained within the 1813 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1814 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1815 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1816 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1817 1818 Negative indices may be passed in idxm and idxn, these rows and columns are 1819 simply ignored. This allows easily inserting element stiffness matrices 1820 with homogeneous Dirichlet boundary conditions that you don't want represented 1821 in the matrix. 1822 1823 Inspired by the structured grid interface to the HYPRE package 1824 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1825 1826 Fortran Note: 1827 `idxm` and `idxn` should be declared as 1828 $ MatStencil idxm(4,m),idxn(4,n) 1829 and the values inserted using 1830 .vb 1831 idxm(MatStencil_i,1) = i 1832 idxm(MatStencil_j,1) = j 1833 idxm(MatStencil_k,1) = k 1834 etc 1835 .ve 1836 1837 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1838 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1839 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1840 @*/ 1841 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1842 { 1843 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1844 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1845 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1846 1847 PetscFunctionBegin; 1848 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1850 PetscValidType(mat, 1); 1851 PetscAssertPointer(idxm, 3); 1852 PetscAssertPointer(idxn, 5); 1853 PetscAssertPointer(v, 6); 1854 1855 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1856 jdxm = buf; 1857 jdxn = buf + m; 1858 } else { 1859 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1860 jdxm = bufm; 1861 jdxn = bufn; 1862 } 1863 for (i = 0; i < m; i++) { 1864 for (j = 0; j < 3 - sdim; j++) dxm++; 1865 tmp = *dxm++ - starts[0]; 1866 for (j = 0; j < sdim - 1; j++) { 1867 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1868 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1869 } 1870 dxm++; 1871 jdxm[i] = tmp; 1872 } 1873 for (i = 0; i < n; i++) { 1874 for (j = 0; j < 3 - sdim; j++) dxn++; 1875 tmp = *dxn++ - starts[0]; 1876 for (j = 0; j < sdim - 1; j++) { 1877 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1878 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1879 } 1880 dxn++; 1881 jdxn[i] = tmp; 1882 } 1883 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1884 PetscCall(PetscFree2(bufm, bufn)); 1885 PetscFunctionReturn(PETSC_SUCCESS); 1886 } 1887 1888 /*@ 1889 MatSetStencil - Sets the grid information for setting values into a matrix via 1890 `MatSetValuesStencil()` 1891 1892 Not Collective 1893 1894 Input Parameters: 1895 + mat - the matrix 1896 . dim - dimension of the grid 1, 2, or 3 1897 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1898 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1899 - dof - number of degrees of freedom per node 1900 1901 Level: beginner 1902 1903 Notes: 1904 Inspired by the structured grid interface to the HYPRE package 1905 (www.llnl.gov/CASC/hyper) 1906 1907 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1908 user. 1909 1910 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1911 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1912 @*/ 1913 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1914 { 1915 PetscFunctionBegin; 1916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1917 PetscAssertPointer(dims, 3); 1918 PetscAssertPointer(starts, 4); 1919 1920 mat->stencil.dim = dim + (dof > 1); 1921 for (PetscInt i = 0; i < dim; i++) { 1922 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1923 mat->stencil.starts[i] = starts[dim - i - 1]; 1924 } 1925 mat->stencil.dims[dim] = dof; 1926 mat->stencil.starts[dim] = 0; 1927 mat->stencil.noc = (PetscBool)(dof == 1); 1928 PetscFunctionReturn(PETSC_SUCCESS); 1929 } 1930 1931 /*@C 1932 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1933 1934 Not Collective 1935 1936 Input Parameters: 1937 + mat - the matrix 1938 . v - a logically two-dimensional array of values 1939 . m - the number of block rows 1940 . idxm - the global block indices 1941 . n - the number of block columns 1942 . idxn - the global block indices 1943 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1944 1945 Level: intermediate 1946 1947 Notes: 1948 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1949 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1950 1951 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1952 NOT the total number of rows/columns; for example, if the block size is 2 and 1953 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1954 The values in `idxm` would be 1 2; that is the first index for each block divided by 1955 the block size. 1956 1957 You must call `MatSetBlockSize()` when constructing this matrix (before 1958 preallocating it). 1959 1960 By default the values, `v`, are row-oriented, so the layout of 1961 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1962 1963 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1964 options cannot be mixed without intervening calls to the assembly 1965 routines. 1966 1967 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1968 as well as in C. 1969 1970 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1971 simply ignored. This allows easily inserting element stiffness matrices 1972 with homogeneous Dirichlet boundary conditions that you don't want represented 1973 in the matrix. 1974 1975 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1976 internal searching must be done to determine where to place the 1977 data in the matrix storage space. By instead inserting blocks of 1978 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1979 reduced. 1980 1981 Example: 1982 .vb 1983 Suppose m=n=2 and block size(bs) = 2 The array is 1984 1985 1 2 | 3 4 1986 5 6 | 7 8 1987 - - - | - - - 1988 9 10 | 11 12 1989 13 14 | 15 16 1990 1991 v[] should be passed in like 1992 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1993 1994 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1995 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1996 .ve 1997 1998 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1999 @*/ 2000 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2001 { 2002 PetscFunctionBeginHot; 2003 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2004 PetscValidType(mat, 1); 2005 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2006 PetscAssertPointer(idxm, 3); 2007 PetscAssertPointer(idxn, 5); 2008 MatCheckPreallocated(mat, 1); 2009 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2010 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2011 if (PetscDefined(USE_DEBUG)) { 2012 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2013 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2014 } 2015 if (PetscDefined(USE_DEBUG)) { 2016 PetscInt rbs, cbs, M, N, i; 2017 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2018 PetscCall(MatGetSize(mat, &M, &N)); 2019 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 2020 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 2021 } 2022 if (mat->assembled) { 2023 mat->was_assembled = PETSC_TRUE; 2024 mat->assembled = PETSC_FALSE; 2025 } 2026 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2027 if (mat->ops->setvaluesblocked) { 2028 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2029 } else { 2030 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2031 PetscInt i, j, bs, cbs; 2032 2033 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2034 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2035 iidxm = buf; 2036 iidxn = buf + m * bs; 2037 } else { 2038 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2039 iidxm = bufr; 2040 iidxn = bufc; 2041 } 2042 for (i = 0; i < m; i++) { 2043 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2044 } 2045 if (m != n || bs != cbs || idxm != idxn) { 2046 for (i = 0; i < n; i++) { 2047 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2048 } 2049 } else iidxn = iidxm; 2050 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2051 PetscCall(PetscFree2(bufr, bufc)); 2052 } 2053 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2054 PetscFunctionReturn(PETSC_SUCCESS); 2055 } 2056 2057 /*@C 2058 MatGetValues - Gets a block of local values from a matrix. 2059 2060 Not Collective; can only return values that are owned by the give process 2061 2062 Input Parameters: 2063 + mat - the matrix 2064 . v - a logically two-dimensional array for storing the values 2065 . m - the number of rows 2066 . idxm - the global indices of the rows 2067 . n - the number of columns 2068 - idxn - the global indices of the columns 2069 2070 Level: advanced 2071 2072 Notes: 2073 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2074 The values, `v`, are then returned in a row-oriented format, 2075 analogous to that used by default in `MatSetValues()`. 2076 2077 `MatGetValues()` uses 0-based row and column numbers in 2078 Fortran as well as in C. 2079 2080 `MatGetValues()` requires that the matrix has been assembled 2081 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2082 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2083 without intermediate matrix assembly. 2084 2085 Negative row or column indices will be ignored and those locations in `v` will be 2086 left unchanged. 2087 2088 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2089 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2090 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2091 2092 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2093 @*/ 2094 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2095 { 2096 PetscFunctionBegin; 2097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2098 PetscValidType(mat, 1); 2099 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2100 PetscAssertPointer(idxm, 3); 2101 PetscAssertPointer(idxn, 5); 2102 PetscAssertPointer(v, 6); 2103 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2104 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2105 MatCheckPreallocated(mat, 1); 2106 2107 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2108 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2109 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2110 PetscFunctionReturn(PETSC_SUCCESS); 2111 } 2112 2113 /*@C 2114 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2115 defined previously by `MatSetLocalToGlobalMapping()` 2116 2117 Not Collective 2118 2119 Input Parameters: 2120 + mat - the matrix 2121 . nrow - number of rows 2122 . irow - the row local indices 2123 . ncol - number of columns 2124 - icol - the column local indices 2125 2126 Output Parameter: 2127 . y - a logically two-dimensional array of values 2128 2129 Level: advanced 2130 2131 Notes: 2132 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2133 2134 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, 2135 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2136 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2137 with `MatSetLocalToGlobalMapping()`. 2138 2139 Developer Note: 2140 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2141 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2142 2143 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2144 `MatSetValuesLocal()`, `MatGetValues()` 2145 @*/ 2146 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2147 { 2148 PetscFunctionBeginHot; 2149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2150 PetscValidType(mat, 1); 2151 MatCheckPreallocated(mat, 1); 2152 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2153 PetscAssertPointer(irow, 3); 2154 PetscAssertPointer(icol, 5); 2155 if (PetscDefined(USE_DEBUG)) { 2156 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2157 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2158 } 2159 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2160 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2161 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2162 else { 2163 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2164 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2165 irowm = buf; 2166 icolm = buf + nrow; 2167 } else { 2168 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2169 irowm = bufr; 2170 icolm = bufc; 2171 } 2172 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2173 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2174 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2175 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2176 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2177 PetscCall(PetscFree2(bufr, bufc)); 2178 } 2179 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2180 PetscFunctionReturn(PETSC_SUCCESS); 2181 } 2182 2183 /*@ 2184 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2185 the same size. Currently, this can only be called once and creates the given matrix. 2186 2187 Not Collective 2188 2189 Input Parameters: 2190 + mat - the matrix 2191 . nb - the number of blocks 2192 . bs - the number of rows (and columns) in each block 2193 . rows - a concatenation of the rows for each block 2194 - v - a concatenation of logically two-dimensional arrays of values 2195 2196 Level: advanced 2197 2198 Notes: 2199 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2200 2201 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2202 2203 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2204 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2205 @*/ 2206 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2207 { 2208 PetscFunctionBegin; 2209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2210 PetscValidType(mat, 1); 2211 PetscAssertPointer(rows, 4); 2212 PetscAssertPointer(v, 5); 2213 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2214 2215 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2216 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2217 else { 2218 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2219 } 2220 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2221 PetscFunctionReturn(PETSC_SUCCESS); 2222 } 2223 2224 /*@ 2225 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2226 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2227 using a local (per-processor) numbering. 2228 2229 Not Collective 2230 2231 Input Parameters: 2232 + x - the matrix 2233 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2234 - cmapping - column mapping 2235 2236 Level: intermediate 2237 2238 Note: 2239 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2240 2241 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2242 @*/ 2243 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2244 { 2245 PetscFunctionBegin; 2246 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2247 PetscValidType(x, 1); 2248 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2249 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2250 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2251 else { 2252 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2253 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2254 } 2255 PetscFunctionReturn(PETSC_SUCCESS); 2256 } 2257 2258 /*@ 2259 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2260 2261 Not Collective 2262 2263 Input Parameter: 2264 . A - the matrix 2265 2266 Output Parameters: 2267 + rmapping - row mapping 2268 - cmapping - column mapping 2269 2270 Level: advanced 2271 2272 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2273 @*/ 2274 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2275 { 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2278 PetscValidType(A, 1); 2279 if (rmapping) { 2280 PetscAssertPointer(rmapping, 2); 2281 *rmapping = A->rmap->mapping; 2282 } 2283 if (cmapping) { 2284 PetscAssertPointer(cmapping, 3); 2285 *cmapping = A->cmap->mapping; 2286 } 2287 PetscFunctionReturn(PETSC_SUCCESS); 2288 } 2289 2290 /*@ 2291 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2292 2293 Logically Collective 2294 2295 Input Parameters: 2296 + A - the matrix 2297 . rmap - row layout 2298 - cmap - column layout 2299 2300 Level: advanced 2301 2302 Note: 2303 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2304 2305 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2306 @*/ 2307 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2308 { 2309 PetscFunctionBegin; 2310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2311 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2312 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2313 PetscFunctionReturn(PETSC_SUCCESS); 2314 } 2315 2316 /*@ 2317 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2318 2319 Not Collective 2320 2321 Input Parameter: 2322 . A - the matrix 2323 2324 Output Parameters: 2325 + rmap - row layout 2326 - cmap - column layout 2327 2328 Level: advanced 2329 2330 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2331 @*/ 2332 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2333 { 2334 PetscFunctionBegin; 2335 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2336 PetscValidType(A, 1); 2337 if (rmap) { 2338 PetscAssertPointer(rmap, 2); 2339 *rmap = A->rmap; 2340 } 2341 if (cmap) { 2342 PetscAssertPointer(cmap, 3); 2343 *cmap = A->cmap; 2344 } 2345 PetscFunctionReturn(PETSC_SUCCESS); 2346 } 2347 2348 /*@C 2349 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2350 using a local numbering of the rows and columns. 2351 2352 Not Collective 2353 2354 Input Parameters: 2355 + mat - the matrix 2356 . nrow - number of rows 2357 . irow - the row local indices 2358 . ncol - number of columns 2359 . icol - the column local indices 2360 . y - a logically two-dimensional array of values 2361 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2362 2363 Level: intermediate 2364 2365 Notes: 2366 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2367 2368 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2369 options cannot be mixed without intervening calls to the assembly 2370 routines. 2371 2372 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2373 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2374 2375 Developer Note: 2376 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2377 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2378 2379 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2380 `MatGetValuesLocal()` 2381 @*/ 2382 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2383 { 2384 PetscFunctionBeginHot; 2385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2386 PetscValidType(mat, 1); 2387 MatCheckPreallocated(mat, 1); 2388 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2389 PetscAssertPointer(irow, 3); 2390 PetscAssertPointer(icol, 5); 2391 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2392 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2393 if (PetscDefined(USE_DEBUG)) { 2394 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2395 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2396 } 2397 2398 if (mat->assembled) { 2399 mat->was_assembled = PETSC_TRUE; 2400 mat->assembled = PETSC_FALSE; 2401 } 2402 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2403 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2404 else { 2405 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2406 const PetscInt *irowm, *icolm; 2407 2408 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2409 bufr = buf; 2410 bufc = buf + nrow; 2411 irowm = bufr; 2412 icolm = bufc; 2413 } else { 2414 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2415 irowm = bufr; 2416 icolm = bufc; 2417 } 2418 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2419 else irowm = irow; 2420 if (mat->cmap->mapping) { 2421 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2422 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2423 } else icolm = irowm; 2424 } else icolm = icol; 2425 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2426 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2427 } 2428 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2429 PetscFunctionReturn(PETSC_SUCCESS); 2430 } 2431 2432 /*@C 2433 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2434 using a local ordering of the nodes a block at a time. 2435 2436 Not Collective 2437 2438 Input Parameters: 2439 + mat - the matrix 2440 . nrow - number of rows 2441 . irow - the row local indices 2442 . ncol - number of columns 2443 . icol - the column local indices 2444 . y - a logically two-dimensional array of values 2445 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2446 2447 Level: intermediate 2448 2449 Notes: 2450 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2451 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2452 2453 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2454 options cannot be mixed without intervening calls to the assembly 2455 routines. 2456 2457 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2458 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2459 2460 Developer Note: 2461 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2462 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2463 2464 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2465 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2466 @*/ 2467 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2468 { 2469 PetscFunctionBeginHot; 2470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2471 PetscValidType(mat, 1); 2472 MatCheckPreallocated(mat, 1); 2473 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2474 PetscAssertPointer(irow, 3); 2475 PetscAssertPointer(icol, 5); 2476 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2477 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2478 if (PetscDefined(USE_DEBUG)) { 2479 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2480 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); 2481 } 2482 2483 if (mat->assembled) { 2484 mat->was_assembled = PETSC_TRUE; 2485 mat->assembled = PETSC_FALSE; 2486 } 2487 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2488 PetscInt irbs, rbs; 2489 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2490 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2491 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2492 } 2493 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2494 PetscInt icbs, cbs; 2495 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2496 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2497 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2498 } 2499 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2500 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2501 else { 2502 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2503 const PetscInt *irowm, *icolm; 2504 2505 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2506 bufr = buf; 2507 bufc = buf + nrow; 2508 irowm = bufr; 2509 icolm = bufc; 2510 } else { 2511 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2512 irowm = bufr; 2513 icolm = bufc; 2514 } 2515 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2516 else irowm = irow; 2517 if (mat->cmap->mapping) { 2518 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2519 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2520 } else icolm = irowm; 2521 } else icolm = icol; 2522 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2523 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2524 } 2525 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2526 PetscFunctionReturn(PETSC_SUCCESS); 2527 } 2528 2529 /*@ 2530 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2531 2532 Collective 2533 2534 Input Parameters: 2535 + mat - the matrix 2536 - x - the vector to be multiplied 2537 2538 Output Parameter: 2539 . y - the result 2540 2541 Level: developer 2542 2543 Note: 2544 The vectors `x` and `y` cannot be the same. I.e., one cannot 2545 call `MatMultDiagonalBlock`(A,y,y). 2546 2547 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2548 @*/ 2549 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2550 { 2551 PetscFunctionBegin; 2552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2553 PetscValidType(mat, 1); 2554 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2555 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2556 2557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2558 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2559 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2560 MatCheckPreallocated(mat, 1); 2561 2562 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2563 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2564 PetscFunctionReturn(PETSC_SUCCESS); 2565 } 2566 2567 /*@ 2568 MatMult - Computes the matrix-vector product, $y = Ax$. 2569 2570 Neighbor-wise Collective 2571 2572 Input Parameters: 2573 + mat - the matrix 2574 - x - the vector to be multiplied 2575 2576 Output Parameter: 2577 . y - the result 2578 2579 Level: beginner 2580 2581 Note: 2582 The vectors `x` and `y` cannot be the same. I.e., one cannot 2583 call `MatMult`(A,y,y). 2584 2585 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2586 @*/ 2587 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2588 { 2589 PetscFunctionBegin; 2590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2591 PetscValidType(mat, 1); 2592 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2593 VecCheckAssembled(x); 2594 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2597 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2598 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); 2599 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); 2600 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); 2601 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); 2602 PetscCall(VecSetErrorIfLocked(y, 3)); 2603 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2604 MatCheckPreallocated(mat, 1); 2605 2606 PetscCall(VecLockReadPush(x)); 2607 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2608 PetscUseTypeMethod(mat, mult, x, y); 2609 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2610 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2611 PetscCall(VecLockReadPop(x)); 2612 PetscFunctionReturn(PETSC_SUCCESS); 2613 } 2614 2615 /*@ 2616 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2617 2618 Neighbor-wise Collective 2619 2620 Input Parameters: 2621 + mat - the matrix 2622 - x - the vector to be multiplied 2623 2624 Output Parameter: 2625 . y - the result 2626 2627 Level: beginner 2628 2629 Notes: 2630 The vectors `x` and `y` cannot be the same. I.e., one cannot 2631 call `MatMultTranspose`(A,y,y). 2632 2633 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2634 use `MatMultHermitianTranspose()` 2635 2636 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2637 @*/ 2638 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2639 { 2640 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2641 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2644 PetscValidType(mat, 1); 2645 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2646 VecCheckAssembled(x); 2647 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2648 2649 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2650 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2651 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2652 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); 2653 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); 2654 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); 2655 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); 2656 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2657 MatCheckPreallocated(mat, 1); 2658 2659 if (!mat->ops->multtranspose) { 2660 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2661 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); 2662 } else op = mat->ops->multtranspose; 2663 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2664 PetscCall(VecLockReadPush(x)); 2665 PetscCall((*op)(mat, x, y)); 2666 PetscCall(VecLockReadPop(x)); 2667 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2668 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2669 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2670 PetscFunctionReturn(PETSC_SUCCESS); 2671 } 2672 2673 /*@ 2674 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2675 2676 Neighbor-wise Collective 2677 2678 Input Parameters: 2679 + mat - the matrix 2680 - x - the vector to be multiplied 2681 2682 Output Parameter: 2683 . y - the result 2684 2685 Level: beginner 2686 2687 Notes: 2688 The vectors `x` and `y` cannot be the same. I.e., one cannot 2689 call `MatMultHermitianTranspose`(A,y,y). 2690 2691 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2692 2693 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2694 2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2696 @*/ 2697 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2698 { 2699 PetscFunctionBegin; 2700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2701 PetscValidType(mat, 1); 2702 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2703 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2704 2705 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2706 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2707 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2708 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); 2709 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); 2710 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); 2711 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); 2712 MatCheckPreallocated(mat, 1); 2713 2714 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2715 #if defined(PETSC_USE_COMPLEX) 2716 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2717 PetscCall(VecLockReadPush(x)); 2718 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2719 else PetscUseTypeMethod(mat, mult, x, y); 2720 PetscCall(VecLockReadPop(x)); 2721 } else { 2722 Vec w; 2723 PetscCall(VecDuplicate(x, &w)); 2724 PetscCall(VecCopy(x, w)); 2725 PetscCall(VecConjugate(w)); 2726 PetscCall(MatMultTranspose(mat, w, y)); 2727 PetscCall(VecDestroy(&w)); 2728 PetscCall(VecConjugate(y)); 2729 } 2730 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2731 #else 2732 PetscCall(MatMultTranspose(mat, x, y)); 2733 #endif 2734 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2735 PetscFunctionReturn(PETSC_SUCCESS); 2736 } 2737 2738 /*@ 2739 MatMultAdd - Computes $v3 = v2 + A * v1$. 2740 2741 Neighbor-wise Collective 2742 2743 Input Parameters: 2744 + mat - the matrix 2745 . v1 - the vector to be multiplied by `mat` 2746 - v2 - the vector to be added to the result 2747 2748 Output Parameter: 2749 . v3 - the result 2750 2751 Level: beginner 2752 2753 Note: 2754 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2755 call `MatMultAdd`(A,v1,v2,v1). 2756 2757 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2758 @*/ 2759 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2760 { 2761 PetscFunctionBegin; 2762 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2763 PetscValidType(mat, 1); 2764 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2765 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2766 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2767 2768 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2769 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2770 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); 2771 /* 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); 2772 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); */ 2773 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); 2774 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); 2775 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2776 MatCheckPreallocated(mat, 1); 2777 2778 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2779 PetscCall(VecLockReadPush(v1)); 2780 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2781 PetscCall(VecLockReadPop(v1)); 2782 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2783 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2784 PetscFunctionReturn(PETSC_SUCCESS); 2785 } 2786 2787 /*@ 2788 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2789 2790 Neighbor-wise Collective 2791 2792 Input Parameters: 2793 + mat - the matrix 2794 . v1 - the vector to be multiplied by the transpose of the matrix 2795 - v2 - the vector to be added to the result 2796 2797 Output Parameter: 2798 . v3 - the result 2799 2800 Level: beginner 2801 2802 Note: 2803 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2804 call `MatMultTransposeAdd`(A,v1,v2,v1). 2805 2806 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2807 @*/ 2808 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2809 { 2810 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2811 2812 PetscFunctionBegin; 2813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2814 PetscValidType(mat, 1); 2815 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2816 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2817 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2818 2819 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2820 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2821 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); 2822 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); 2823 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); 2824 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2825 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2826 MatCheckPreallocated(mat, 1); 2827 2828 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2829 PetscCall(VecLockReadPush(v1)); 2830 PetscCall((*op)(mat, v1, v2, v3)); 2831 PetscCall(VecLockReadPop(v1)); 2832 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2833 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2834 PetscFunctionReturn(PETSC_SUCCESS); 2835 } 2836 2837 /*@ 2838 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2839 2840 Neighbor-wise Collective 2841 2842 Input Parameters: 2843 + mat - the matrix 2844 . v1 - the vector to be multiplied by the Hermitian transpose 2845 - v2 - the vector to be added to the result 2846 2847 Output Parameter: 2848 . v3 - the result 2849 2850 Level: beginner 2851 2852 Note: 2853 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2854 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2855 2856 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2857 @*/ 2858 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2859 { 2860 PetscFunctionBegin; 2861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2862 PetscValidType(mat, 1); 2863 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2864 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2865 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2866 2867 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2868 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2869 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2870 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); 2871 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); 2872 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); 2873 MatCheckPreallocated(mat, 1); 2874 2875 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2876 PetscCall(VecLockReadPush(v1)); 2877 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2878 else { 2879 Vec w, z; 2880 PetscCall(VecDuplicate(v1, &w)); 2881 PetscCall(VecCopy(v1, w)); 2882 PetscCall(VecConjugate(w)); 2883 PetscCall(VecDuplicate(v3, &z)); 2884 PetscCall(MatMultTranspose(mat, w, z)); 2885 PetscCall(VecDestroy(&w)); 2886 PetscCall(VecConjugate(z)); 2887 if (v2 != v3) { 2888 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2889 } else { 2890 PetscCall(VecAXPY(v3, 1.0, z)); 2891 } 2892 PetscCall(VecDestroy(&z)); 2893 } 2894 PetscCall(VecLockReadPop(v1)); 2895 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2896 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2897 PetscFunctionReturn(PETSC_SUCCESS); 2898 } 2899 2900 /*@C 2901 MatGetFactorType - gets the type of factorization a matrix is 2902 2903 Not Collective 2904 2905 Input Parameter: 2906 . mat - the matrix 2907 2908 Output Parameter: 2909 . 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` 2910 2911 Level: intermediate 2912 2913 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2914 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2915 @*/ 2916 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2917 { 2918 PetscFunctionBegin; 2919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2920 PetscValidType(mat, 1); 2921 PetscAssertPointer(t, 2); 2922 *t = mat->factortype; 2923 PetscFunctionReturn(PETSC_SUCCESS); 2924 } 2925 2926 /*@C 2927 MatSetFactorType - sets the type of factorization a matrix is 2928 2929 Logically Collective 2930 2931 Input Parameters: 2932 + mat - the matrix 2933 - 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` 2934 2935 Level: intermediate 2936 2937 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2938 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2939 @*/ 2940 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2941 { 2942 PetscFunctionBegin; 2943 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2944 PetscValidType(mat, 1); 2945 mat->factortype = t; 2946 PetscFunctionReturn(PETSC_SUCCESS); 2947 } 2948 2949 /*@C 2950 MatGetInfo - Returns information about matrix storage (number of 2951 nonzeros, memory, etc.). 2952 2953 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2954 2955 Input Parameters: 2956 + mat - the matrix 2957 - 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) 2958 2959 Output Parameter: 2960 . info - matrix information context 2961 2962 Options Database Key: 2963 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2964 2965 Notes: 2966 The `MatInfo` context contains a variety of matrix data, including 2967 number of nonzeros allocated and used, number of mallocs during 2968 matrix assembly, etc. Additional information for factored matrices 2969 is provided (such as the fill ratio, number of mallocs during 2970 factorization, etc.). 2971 2972 Example: 2973 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2974 data within the MatInfo context. For example, 2975 .vb 2976 MatInfo info; 2977 Mat A; 2978 double mal, nz_a, nz_u; 2979 2980 MatGetInfo(A, MAT_LOCAL, &info); 2981 mal = info.mallocs; 2982 nz_a = info.nz_allocated; 2983 .ve 2984 2985 Fortran users should declare info as a double precision 2986 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2987 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2988 a complete list of parameter names. 2989 .vb 2990 double precision info(MAT_INFO_SIZE) 2991 double precision mal, nz_a 2992 Mat A 2993 integer ierr 2994 2995 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2996 mal = info(MAT_INFO_MALLOCS) 2997 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2998 .ve 2999 3000 Level: intermediate 3001 3002 Developer Note: 3003 The Fortran interface is not autogenerated as the 3004 interface definition cannot be generated correctly [due to `MatInfo` argument] 3005 3006 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3007 @*/ 3008 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3009 { 3010 PetscFunctionBegin; 3011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3012 PetscValidType(mat, 1); 3013 PetscAssertPointer(info, 3); 3014 MatCheckPreallocated(mat, 1); 3015 PetscUseTypeMethod(mat, getinfo, flag, info); 3016 PetscFunctionReturn(PETSC_SUCCESS); 3017 } 3018 3019 /* 3020 This is used by external packages where it is not easy to get the info from the actual 3021 matrix factorization. 3022 */ 3023 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3024 { 3025 PetscFunctionBegin; 3026 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3027 PetscFunctionReturn(PETSC_SUCCESS); 3028 } 3029 3030 /*@C 3031 MatLUFactor - Performs in-place LU factorization of matrix. 3032 3033 Collective 3034 3035 Input Parameters: 3036 + mat - the matrix 3037 . row - row permutation 3038 . col - column permutation 3039 - info - options for factorization, includes 3040 .vb 3041 fill - expected fill as ratio of original fill. 3042 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3043 Run with the option -info to determine an optimal value to use 3044 .ve 3045 3046 Level: developer 3047 3048 Notes: 3049 Most users should employ the `KSP` interface for linear solvers 3050 instead of working directly with matrix algebra routines such as this. 3051 See, e.g., `KSPCreate()`. 3052 3053 This changes the state of the matrix to a factored matrix; it cannot be used 3054 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3055 3056 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3057 when not using `KSP`. 3058 3059 Developer Note: 3060 The Fortran interface is not autogenerated as the 3061 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3062 3063 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3064 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3065 @*/ 3066 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3067 { 3068 MatFactorInfo tinfo; 3069 3070 PetscFunctionBegin; 3071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3072 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3073 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3074 if (info) PetscAssertPointer(info, 4); 3075 PetscValidType(mat, 1); 3076 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3077 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3078 MatCheckPreallocated(mat, 1); 3079 if (!info) { 3080 PetscCall(MatFactorInfoInitialize(&tinfo)); 3081 info = &tinfo; 3082 } 3083 3084 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3085 PetscUseTypeMethod(mat, lufactor, row, col, info); 3086 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3087 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3088 PetscFunctionReturn(PETSC_SUCCESS); 3089 } 3090 3091 /*@C 3092 MatILUFactor - Performs in-place ILU factorization of matrix. 3093 3094 Collective 3095 3096 Input Parameters: 3097 + mat - the matrix 3098 . row - row permutation 3099 . col - column permutation 3100 - info - structure containing 3101 .vb 3102 levels - number of levels of fill. 3103 expected fill - as ratio of original fill. 3104 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3105 missing diagonal entries) 3106 .ve 3107 3108 Level: developer 3109 3110 Notes: 3111 Most users should employ the `KSP` interface for linear solvers 3112 instead of working directly with matrix algebra routines such as this. 3113 See, e.g., `KSPCreate()`. 3114 3115 Probably really in-place only when level of fill is zero, otherwise allocates 3116 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3117 when not using `KSP`. 3118 3119 Developer Note: 3120 The Fortran interface is not autogenerated as the 3121 interface definition cannot be generated correctly [due to MatFactorInfo] 3122 3123 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3124 @*/ 3125 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3126 { 3127 PetscFunctionBegin; 3128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3129 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3130 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3131 PetscAssertPointer(info, 4); 3132 PetscValidType(mat, 1); 3133 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3134 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3135 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3136 MatCheckPreallocated(mat, 1); 3137 3138 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3139 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3140 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3141 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3142 PetscFunctionReturn(PETSC_SUCCESS); 3143 } 3144 3145 /*@C 3146 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3147 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3148 3149 Collective 3150 3151 Input Parameters: 3152 + fact - the factor matrix obtained with `MatGetFactor()` 3153 . mat - the matrix 3154 . row - the row permutation 3155 . col - the column permutation 3156 - info - options for factorization, includes 3157 .vb 3158 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3159 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3160 .ve 3161 3162 Level: developer 3163 3164 Notes: 3165 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3166 3167 Most users should employ the simplified `KSP` interface for linear solvers 3168 instead of working directly with matrix algebra routines such as this. 3169 See, e.g., `KSPCreate()`. 3170 3171 Developer Note: 3172 The Fortran interface is not autogenerated as the 3173 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3174 3175 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3176 @*/ 3177 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3178 { 3179 MatFactorInfo tinfo; 3180 3181 PetscFunctionBegin; 3182 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3184 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3185 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3186 if (info) PetscAssertPointer(info, 5); 3187 PetscValidType(fact, 1); 3188 PetscValidType(mat, 2); 3189 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3191 MatCheckPreallocated(mat, 2); 3192 if (!info) { 3193 PetscCall(MatFactorInfoInitialize(&tinfo)); 3194 info = &tinfo; 3195 } 3196 3197 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3198 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3199 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3200 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3201 PetscFunctionReturn(PETSC_SUCCESS); 3202 } 3203 3204 /*@C 3205 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3206 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3207 3208 Collective 3209 3210 Input Parameters: 3211 + fact - the factor matrix obtained with `MatGetFactor()` 3212 . mat - the matrix 3213 - info - options for factorization 3214 3215 Level: developer 3216 3217 Notes: 3218 See `MatLUFactor()` for in-place factorization. See 3219 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3220 3221 Most users should employ the `KSP` interface for linear solvers 3222 instead of working directly with matrix algebra routines such as this. 3223 See, e.g., `KSPCreate()`. 3224 3225 Developer Note: 3226 The Fortran interface is not autogenerated as the 3227 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3228 3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3230 @*/ 3231 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3232 { 3233 MatFactorInfo tinfo; 3234 3235 PetscFunctionBegin; 3236 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3238 PetscValidType(fact, 1); 3239 PetscValidType(mat, 2); 3240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3241 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, 3242 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3243 3244 MatCheckPreallocated(mat, 2); 3245 if (!info) { 3246 PetscCall(MatFactorInfoInitialize(&tinfo)); 3247 info = &tinfo; 3248 } 3249 3250 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3251 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3252 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3253 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3254 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3255 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3256 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3257 PetscFunctionReturn(PETSC_SUCCESS); 3258 } 3259 3260 /*@C 3261 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3262 symmetric matrix. 3263 3264 Collective 3265 3266 Input Parameters: 3267 + mat - the matrix 3268 . perm - row and column permutations 3269 - info - expected fill as ratio of original fill 3270 3271 Level: developer 3272 3273 Notes: 3274 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3275 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3276 3277 Most users should employ the `KSP` interface for linear solvers 3278 instead of working directly with matrix algebra routines such as this. 3279 See, e.g., `KSPCreate()`. 3280 3281 Developer Note: 3282 The Fortran interface is not autogenerated as the 3283 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3284 3285 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3286 `MatGetOrdering()` 3287 @*/ 3288 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3289 { 3290 MatFactorInfo tinfo; 3291 3292 PetscFunctionBegin; 3293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3294 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3295 if (info) PetscAssertPointer(info, 3); 3296 PetscValidType(mat, 1); 3297 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3298 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3299 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3300 MatCheckPreallocated(mat, 1); 3301 if (!info) { 3302 PetscCall(MatFactorInfoInitialize(&tinfo)); 3303 info = &tinfo; 3304 } 3305 3306 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3307 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3308 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3309 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3310 PetscFunctionReturn(PETSC_SUCCESS); 3311 } 3312 3313 /*@C 3314 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3315 of a symmetric matrix. 3316 3317 Collective 3318 3319 Input Parameters: 3320 + fact - the factor matrix obtained with `MatGetFactor()` 3321 . mat - the matrix 3322 . perm - row and column permutations 3323 - info - options for factorization, includes 3324 .vb 3325 fill - expected fill as ratio of original fill. 3326 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3327 Run with the option -info to determine an optimal value to use 3328 .ve 3329 3330 Level: developer 3331 3332 Notes: 3333 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3334 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3335 3336 Most users should employ the `KSP` interface for linear solvers 3337 instead of working directly with matrix algebra routines such as this. 3338 See, e.g., `KSPCreate()`. 3339 3340 Developer Note: 3341 The Fortran interface is not autogenerated as the 3342 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3343 3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3345 `MatGetOrdering()` 3346 @*/ 3347 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3348 { 3349 MatFactorInfo tinfo; 3350 3351 PetscFunctionBegin; 3352 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3353 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3354 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3355 if (info) PetscAssertPointer(info, 4); 3356 PetscValidType(fact, 1); 3357 PetscValidType(mat, 2); 3358 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3361 MatCheckPreallocated(mat, 2); 3362 if (!info) { 3363 PetscCall(MatFactorInfoInitialize(&tinfo)); 3364 info = &tinfo; 3365 } 3366 3367 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3368 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3369 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3370 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3371 PetscFunctionReturn(PETSC_SUCCESS); 3372 } 3373 3374 /*@C 3375 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3376 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3377 `MatCholeskyFactorSymbolic()`. 3378 3379 Collective 3380 3381 Input Parameters: 3382 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3383 . mat - the initial matrix that is to be factored 3384 - info - options for factorization 3385 3386 Level: developer 3387 3388 Note: 3389 Most users should employ the `KSP` interface for linear solvers 3390 instead of working directly with matrix algebra routines such as this. 3391 See, e.g., `KSPCreate()`. 3392 3393 Developer Note: 3394 The Fortran interface is not autogenerated as the 3395 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3396 3397 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3398 @*/ 3399 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3400 { 3401 MatFactorInfo tinfo; 3402 3403 PetscFunctionBegin; 3404 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3406 PetscValidType(fact, 1); 3407 PetscValidType(mat, 2); 3408 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3409 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, 3410 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3411 MatCheckPreallocated(mat, 2); 3412 if (!info) { 3413 PetscCall(MatFactorInfoInitialize(&tinfo)); 3414 info = &tinfo; 3415 } 3416 3417 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3418 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3419 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3420 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3421 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3422 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3423 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3424 PetscFunctionReturn(PETSC_SUCCESS); 3425 } 3426 3427 /*@ 3428 MatQRFactor - Performs in-place QR factorization of matrix. 3429 3430 Collective 3431 3432 Input Parameters: 3433 + mat - the matrix 3434 . col - column permutation 3435 - info - options for factorization, includes 3436 .vb 3437 fill - expected fill as ratio of original fill. 3438 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3439 Run with the option -info to determine an optimal value to use 3440 .ve 3441 3442 Level: developer 3443 3444 Notes: 3445 Most users should employ the `KSP` interface for linear solvers 3446 instead of working directly with matrix algebra routines such as this. 3447 See, e.g., `KSPCreate()`. 3448 3449 This changes the state of the matrix to a factored matrix; it cannot be used 3450 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3451 3452 Developer Note: 3453 The Fortran interface is not autogenerated as the 3454 interface definition cannot be generated correctly [due to MatFactorInfo] 3455 3456 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3457 `MatSetUnfactored()` 3458 @*/ 3459 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3460 { 3461 PetscFunctionBegin; 3462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3463 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3464 if (info) PetscAssertPointer(info, 3); 3465 PetscValidType(mat, 1); 3466 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3467 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3468 MatCheckPreallocated(mat, 1); 3469 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3470 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3471 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3472 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3473 PetscFunctionReturn(PETSC_SUCCESS); 3474 } 3475 3476 /*@ 3477 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3478 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3479 3480 Collective 3481 3482 Input Parameters: 3483 + fact - the factor matrix obtained with `MatGetFactor()` 3484 . mat - the matrix 3485 . col - column permutation 3486 - info - options for factorization, includes 3487 .vb 3488 fill - expected fill as ratio of original fill. 3489 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3490 Run with the option -info to determine an optimal value to use 3491 .ve 3492 3493 Level: developer 3494 3495 Note: 3496 Most users should employ the `KSP` interface for linear solvers 3497 instead of working directly with matrix algebra routines such as this. 3498 See, e.g., `KSPCreate()`. 3499 3500 Developer Note: 3501 The Fortran interface is not autogenerated as the 3502 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3503 3504 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3505 @*/ 3506 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3507 { 3508 MatFactorInfo tinfo; 3509 3510 PetscFunctionBegin; 3511 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3512 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3513 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3514 if (info) PetscAssertPointer(info, 4); 3515 PetscValidType(fact, 1); 3516 PetscValidType(mat, 2); 3517 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3518 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3519 MatCheckPreallocated(mat, 2); 3520 if (!info) { 3521 PetscCall(MatFactorInfoInitialize(&tinfo)); 3522 info = &tinfo; 3523 } 3524 3525 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3526 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3527 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3528 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3529 PetscFunctionReturn(PETSC_SUCCESS); 3530 } 3531 3532 /*@ 3533 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3534 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3535 3536 Collective 3537 3538 Input Parameters: 3539 + fact - the factor matrix obtained with `MatGetFactor()` 3540 . mat - the matrix 3541 - info - options for factorization 3542 3543 Level: developer 3544 3545 Notes: 3546 See `MatQRFactor()` for in-place factorization. 3547 3548 Most users should employ the `KSP` interface for linear solvers 3549 instead of working directly with matrix algebra routines such as this. 3550 See, e.g., `KSPCreate()`. 3551 3552 Developer Note: 3553 The Fortran interface is not autogenerated as the 3554 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3555 3556 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3557 @*/ 3558 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3559 { 3560 MatFactorInfo tinfo; 3561 3562 PetscFunctionBegin; 3563 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3565 PetscValidType(fact, 1); 3566 PetscValidType(mat, 2); 3567 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3568 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, 3569 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3570 3571 MatCheckPreallocated(mat, 2); 3572 if (!info) { 3573 PetscCall(MatFactorInfoInitialize(&tinfo)); 3574 info = &tinfo; 3575 } 3576 3577 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3578 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3579 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3580 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3581 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3582 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3583 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3584 PetscFunctionReturn(PETSC_SUCCESS); 3585 } 3586 3587 /*@ 3588 MatSolve - Solves $A x = b$, given a factored matrix. 3589 3590 Neighbor-wise Collective 3591 3592 Input Parameters: 3593 + mat - the factored matrix 3594 - b - the right-hand-side vector 3595 3596 Output Parameter: 3597 . x - the result vector 3598 3599 Level: developer 3600 3601 Notes: 3602 The vectors `b` and `x` cannot be the same. I.e., one cannot 3603 call `MatSolve`(A,x,x). 3604 3605 Most users should employ the `KSP` interface for linear solvers 3606 instead of working directly with matrix algebra routines such as this. 3607 See, e.g., `KSPCreate()`. 3608 3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3610 @*/ 3611 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3612 { 3613 PetscFunctionBegin; 3614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3615 PetscValidType(mat, 1); 3616 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3617 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3618 PetscCheckSameComm(mat, 1, b, 2); 3619 PetscCheckSameComm(mat, 1, x, 3); 3620 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3621 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); 3622 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); 3623 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); 3624 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3625 MatCheckPreallocated(mat, 1); 3626 3627 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3628 if (mat->factorerrortype) { 3629 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3630 PetscCall(VecSetInf(x)); 3631 } else PetscUseTypeMethod(mat, solve, b, x); 3632 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3633 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3634 PetscFunctionReturn(PETSC_SUCCESS); 3635 } 3636 3637 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3638 { 3639 Vec b, x; 3640 PetscInt N, i; 3641 PetscErrorCode (*f)(Mat, Vec, Vec); 3642 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3643 3644 PetscFunctionBegin; 3645 if (A->factorerrortype) { 3646 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3647 PetscCall(MatSetInf(X)); 3648 PetscFunctionReturn(PETSC_SUCCESS); 3649 } 3650 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3651 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3652 PetscCall(MatBoundToCPU(A, &Abound)); 3653 if (!Abound) { 3654 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3655 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3656 } 3657 #if PetscDefined(HAVE_CUDA) 3658 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3659 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3660 #elif PetscDefined(HAVE_HIP) 3661 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3662 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3663 #endif 3664 PetscCall(MatGetSize(B, NULL, &N)); 3665 for (i = 0; i < N; i++) { 3666 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3667 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3668 PetscCall((*f)(A, b, x)); 3669 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3670 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3671 } 3672 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3673 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3674 PetscFunctionReturn(PETSC_SUCCESS); 3675 } 3676 3677 /*@ 3678 MatMatSolve - Solves $A X = B$, given a factored matrix. 3679 3680 Neighbor-wise Collective 3681 3682 Input Parameters: 3683 + A - the factored matrix 3684 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3685 3686 Output Parameter: 3687 . X - the result matrix (dense matrix) 3688 3689 Level: developer 3690 3691 Note: 3692 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3693 otherwise, `B` and `X` cannot be the same. 3694 3695 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3696 @*/ 3697 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3698 { 3699 PetscFunctionBegin; 3700 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3701 PetscValidType(A, 1); 3702 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3703 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3704 PetscCheckSameComm(A, 1, B, 2); 3705 PetscCheckSameComm(A, 1, X, 3); 3706 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); 3707 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); 3708 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"); 3709 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3710 MatCheckPreallocated(A, 1); 3711 3712 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3713 if (!A->ops->matsolve) { 3714 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3715 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3716 } else PetscUseTypeMethod(A, matsolve, B, X); 3717 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3718 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3719 PetscFunctionReturn(PETSC_SUCCESS); 3720 } 3721 3722 /*@ 3723 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3724 3725 Neighbor-wise Collective 3726 3727 Input Parameters: 3728 + A - the factored matrix 3729 - B - the right-hand-side matrix (`MATDENSE` matrix) 3730 3731 Output Parameter: 3732 . X - the result matrix (dense matrix) 3733 3734 Level: developer 3735 3736 Note: 3737 The matrices `B` and `X` cannot be the same. I.e., one cannot 3738 call `MatMatSolveTranspose`(A,X,X). 3739 3740 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3741 @*/ 3742 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3743 { 3744 PetscFunctionBegin; 3745 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3746 PetscValidType(A, 1); 3747 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3748 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3749 PetscCheckSameComm(A, 1, B, 2); 3750 PetscCheckSameComm(A, 1, X, 3); 3751 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3752 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); 3753 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); 3754 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); 3755 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"); 3756 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3757 MatCheckPreallocated(A, 1); 3758 3759 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3760 if (!A->ops->matsolvetranspose) { 3761 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3762 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3763 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3764 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3765 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3766 PetscFunctionReturn(PETSC_SUCCESS); 3767 } 3768 3769 /*@ 3770 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3771 3772 Neighbor-wise Collective 3773 3774 Input Parameters: 3775 + A - the factored matrix 3776 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3777 3778 Output Parameter: 3779 . X - the result matrix (dense matrix) 3780 3781 Level: developer 3782 3783 Note: 3784 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 3785 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3786 3787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3788 @*/ 3789 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3790 { 3791 PetscFunctionBegin; 3792 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3793 PetscValidType(A, 1); 3794 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3795 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3796 PetscCheckSameComm(A, 1, Bt, 2); 3797 PetscCheckSameComm(A, 1, X, 3); 3798 3799 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3800 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); 3801 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); 3802 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"); 3803 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3804 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3805 MatCheckPreallocated(A, 1); 3806 3807 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3808 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3809 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3810 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3811 PetscFunctionReturn(PETSC_SUCCESS); 3812 } 3813 3814 /*@ 3815 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3816 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3817 3818 Neighbor-wise Collective 3819 3820 Input Parameters: 3821 + mat - the factored matrix 3822 - b - the right-hand-side vector 3823 3824 Output Parameter: 3825 . x - the result vector 3826 3827 Level: developer 3828 3829 Notes: 3830 `MatSolve()` should be used for most applications, as it performs 3831 a forward solve followed by a backward solve. 3832 3833 The vectors `b` and `x` cannot be the same, i.e., one cannot 3834 call `MatForwardSolve`(A,x,x). 3835 3836 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3837 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3838 `MatForwardSolve()` solves $U^T*D y = b$, and 3839 `MatBackwardSolve()` solves $U x = y$. 3840 Thus they do not provide a symmetric preconditioner. 3841 3842 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3843 @*/ 3844 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3845 { 3846 PetscFunctionBegin; 3847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3848 PetscValidType(mat, 1); 3849 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3850 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3851 PetscCheckSameComm(mat, 1, b, 2); 3852 PetscCheckSameComm(mat, 1, x, 3); 3853 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3854 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); 3855 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); 3856 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); 3857 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3858 MatCheckPreallocated(mat, 1); 3859 3860 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3861 PetscUseTypeMethod(mat, forwardsolve, b, x); 3862 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3863 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3864 PetscFunctionReturn(PETSC_SUCCESS); 3865 } 3866 3867 /*@ 3868 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3869 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3870 3871 Neighbor-wise Collective 3872 3873 Input Parameters: 3874 + mat - the factored matrix 3875 - b - the right-hand-side vector 3876 3877 Output Parameter: 3878 . x - the result vector 3879 3880 Level: developer 3881 3882 Notes: 3883 `MatSolve()` should be used for most applications, as it performs 3884 a forward solve followed by a backward solve. 3885 3886 The vectors `b` and `x` cannot be the same. I.e., one cannot 3887 call `MatBackwardSolve`(A,x,x). 3888 3889 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3890 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3891 `MatForwardSolve()` solves $U^T*D y = b$, and 3892 `MatBackwardSolve()` solves $U x = y$. 3893 Thus they do not provide a symmetric preconditioner. 3894 3895 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3896 @*/ 3897 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3898 { 3899 PetscFunctionBegin; 3900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3901 PetscValidType(mat, 1); 3902 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3903 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3904 PetscCheckSameComm(mat, 1, b, 2); 3905 PetscCheckSameComm(mat, 1, x, 3); 3906 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3907 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); 3908 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); 3909 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); 3910 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3911 MatCheckPreallocated(mat, 1); 3912 3913 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3914 PetscUseTypeMethod(mat, backwardsolve, b, x); 3915 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3916 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3917 PetscFunctionReturn(PETSC_SUCCESS); 3918 } 3919 3920 /*@ 3921 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3922 3923 Neighbor-wise Collective 3924 3925 Input Parameters: 3926 + mat - the factored matrix 3927 . b - the right-hand-side vector 3928 - y - the vector to be added to 3929 3930 Output Parameter: 3931 . x - the result vector 3932 3933 Level: developer 3934 3935 Note: 3936 The vectors `b` and `x` cannot be the same. I.e., one cannot 3937 call `MatSolveAdd`(A,x,y,x). 3938 3939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3940 @*/ 3941 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3942 { 3943 PetscScalar one = 1.0; 3944 Vec tmp; 3945 3946 PetscFunctionBegin; 3947 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3948 PetscValidType(mat, 1); 3949 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3950 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3951 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3952 PetscCheckSameComm(mat, 1, b, 2); 3953 PetscCheckSameComm(mat, 1, y, 3); 3954 PetscCheckSameComm(mat, 1, x, 4); 3955 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3956 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); 3957 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); 3958 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); 3959 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); 3960 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); 3961 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3962 MatCheckPreallocated(mat, 1); 3963 3964 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3965 if (mat->factorerrortype) { 3966 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3967 PetscCall(VecSetInf(x)); 3968 } else if (mat->ops->solveadd) { 3969 PetscUseTypeMethod(mat, solveadd, b, y, x); 3970 } else { 3971 /* do the solve then the add manually */ 3972 if (x != y) { 3973 PetscCall(MatSolve(mat, b, x)); 3974 PetscCall(VecAXPY(x, one, y)); 3975 } else { 3976 PetscCall(VecDuplicate(x, &tmp)); 3977 PetscCall(VecCopy(x, tmp)); 3978 PetscCall(MatSolve(mat, b, x)); 3979 PetscCall(VecAXPY(x, one, tmp)); 3980 PetscCall(VecDestroy(&tmp)); 3981 } 3982 } 3983 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3984 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3985 PetscFunctionReturn(PETSC_SUCCESS); 3986 } 3987 3988 /*@ 3989 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 3990 3991 Neighbor-wise Collective 3992 3993 Input Parameters: 3994 + mat - the factored matrix 3995 - b - the right-hand-side vector 3996 3997 Output Parameter: 3998 . x - the result vector 3999 4000 Level: developer 4001 4002 Notes: 4003 The vectors `b` and `x` cannot be the same. I.e., one cannot 4004 call `MatSolveTranspose`(A,x,x). 4005 4006 Most users should employ the `KSP` interface for linear solvers 4007 instead of working directly with matrix algebra routines such as this. 4008 See, e.g., `KSPCreate()`. 4009 4010 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4011 @*/ 4012 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4013 { 4014 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4015 4016 PetscFunctionBegin; 4017 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4018 PetscValidType(mat, 1); 4019 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4020 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4021 PetscCheckSameComm(mat, 1, b, 2); 4022 PetscCheckSameComm(mat, 1, x, 3); 4023 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4024 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); 4025 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); 4026 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4027 MatCheckPreallocated(mat, 1); 4028 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4029 if (mat->factorerrortype) { 4030 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4031 PetscCall(VecSetInf(x)); 4032 } else { 4033 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4034 PetscCall((*f)(mat, b, x)); 4035 } 4036 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4037 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4038 PetscFunctionReturn(PETSC_SUCCESS); 4039 } 4040 4041 /*@ 4042 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4043 factored matrix. 4044 4045 Neighbor-wise Collective 4046 4047 Input Parameters: 4048 + mat - the factored matrix 4049 . b - the right-hand-side vector 4050 - y - the vector to be added to 4051 4052 Output Parameter: 4053 . x - the result vector 4054 4055 Level: developer 4056 4057 Note: 4058 The vectors `b` and `x` cannot be the same. I.e., one cannot 4059 call `MatSolveTransposeAdd`(A,x,y,x). 4060 4061 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4062 @*/ 4063 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4064 { 4065 PetscScalar one = 1.0; 4066 Vec tmp; 4067 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4068 4069 PetscFunctionBegin; 4070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4071 PetscValidType(mat, 1); 4072 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4073 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4074 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4075 PetscCheckSameComm(mat, 1, b, 2); 4076 PetscCheckSameComm(mat, 1, y, 3); 4077 PetscCheckSameComm(mat, 1, x, 4); 4078 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4079 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); 4080 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); 4081 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); 4082 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); 4083 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4084 MatCheckPreallocated(mat, 1); 4085 4086 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4087 if (mat->factorerrortype) { 4088 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4089 PetscCall(VecSetInf(x)); 4090 } else if (f) { 4091 PetscCall((*f)(mat, b, y, x)); 4092 } else { 4093 /* do the solve then the add manually */ 4094 if (x != y) { 4095 PetscCall(MatSolveTranspose(mat, b, x)); 4096 PetscCall(VecAXPY(x, one, y)); 4097 } else { 4098 PetscCall(VecDuplicate(x, &tmp)); 4099 PetscCall(VecCopy(x, tmp)); 4100 PetscCall(MatSolveTranspose(mat, b, x)); 4101 PetscCall(VecAXPY(x, one, tmp)); 4102 PetscCall(VecDestroy(&tmp)); 4103 } 4104 } 4105 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4106 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4107 PetscFunctionReturn(PETSC_SUCCESS); 4108 } 4109 4110 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4111 /*@ 4112 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4113 4114 Neighbor-wise Collective 4115 4116 Input Parameters: 4117 + mat - the matrix 4118 . b - the right hand side 4119 . omega - the relaxation factor 4120 . flag - flag indicating the type of SOR (see below) 4121 . shift - diagonal shift 4122 . its - the number of iterations 4123 - lits - the number of local iterations 4124 4125 Output Parameter: 4126 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4127 4128 SOR Flags: 4129 + `SOR_FORWARD_SWEEP` - forward SOR 4130 . `SOR_BACKWARD_SWEEP` - backward SOR 4131 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4132 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4133 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4134 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4135 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4136 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4137 upper/lower triangular part of matrix to 4138 vector (with omega) 4139 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4140 4141 Level: developer 4142 4143 Notes: 4144 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4145 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4146 on each processor. 4147 4148 Application programmers will not generally use `MatSOR()` directly, 4149 but instead will employ the `KSP`/`PC` interface. 4150 4151 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4152 4153 Most users should employ the `KSP` interface for linear solvers 4154 instead of working directly with matrix algebra routines such as this. 4155 See, e.g., `KSPCreate()`. 4156 4157 Vectors `x` and `b` CANNOT be the same 4158 4159 The flags are implemented as bitwise inclusive or operations. 4160 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4161 to specify a zero initial guess for SSOR. 4162 4163 Developer Note: 4164 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4165 4166 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4167 @*/ 4168 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4169 { 4170 PetscFunctionBegin; 4171 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4172 PetscValidType(mat, 1); 4173 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4174 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4175 PetscCheckSameComm(mat, 1, b, 2); 4176 PetscCheckSameComm(mat, 1, x, 8); 4177 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4178 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4179 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); 4180 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); 4181 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); 4182 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4183 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4184 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4185 4186 MatCheckPreallocated(mat, 1); 4187 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4188 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4189 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4190 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4191 PetscFunctionReturn(PETSC_SUCCESS); 4192 } 4193 4194 /* 4195 Default matrix copy routine. 4196 */ 4197 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4198 { 4199 PetscInt i, rstart = 0, rend = 0, nz; 4200 const PetscInt *cwork; 4201 const PetscScalar *vwork; 4202 4203 PetscFunctionBegin; 4204 if (B->assembled) PetscCall(MatZeroEntries(B)); 4205 if (str == SAME_NONZERO_PATTERN) { 4206 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4207 for (i = rstart; i < rend; i++) { 4208 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4209 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4210 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4211 } 4212 } else { 4213 PetscCall(MatAYPX(B, 0.0, A, str)); 4214 } 4215 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4216 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4217 PetscFunctionReturn(PETSC_SUCCESS); 4218 } 4219 4220 /*@ 4221 MatCopy - Copies a matrix to another matrix. 4222 4223 Collective 4224 4225 Input Parameters: 4226 + A - the matrix 4227 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4228 4229 Output Parameter: 4230 . B - where the copy is put 4231 4232 Level: intermediate 4233 4234 Notes: 4235 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4236 4237 `MatCopy()` copies the matrix entries of a matrix to another existing 4238 matrix (after first zeroing the second matrix). A related routine is 4239 `MatConvert()`, which first creates a new matrix and then copies the data. 4240 4241 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4242 @*/ 4243 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4244 { 4245 PetscInt i; 4246 4247 PetscFunctionBegin; 4248 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4249 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4250 PetscValidType(A, 1); 4251 PetscValidType(B, 2); 4252 PetscCheckSameComm(A, 1, B, 2); 4253 MatCheckPreallocated(B, 2); 4254 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4255 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4256 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, 4257 A->cmap->N, B->cmap->N); 4258 MatCheckPreallocated(A, 1); 4259 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4260 4261 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4262 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4263 else PetscCall(MatCopy_Basic(A, B, str)); 4264 4265 B->stencil.dim = A->stencil.dim; 4266 B->stencil.noc = A->stencil.noc; 4267 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4268 B->stencil.dims[i] = A->stencil.dims[i]; 4269 B->stencil.starts[i] = A->stencil.starts[i]; 4270 } 4271 4272 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4273 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4274 PetscFunctionReturn(PETSC_SUCCESS); 4275 } 4276 4277 /*@C 4278 MatConvert - Converts a matrix to another matrix, either of the same 4279 or different type. 4280 4281 Collective 4282 4283 Input Parameters: 4284 + mat - the matrix 4285 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4286 same type as the original matrix. 4287 - reuse - denotes if the destination matrix is to be created or reused. 4288 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 4289 `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). 4290 4291 Output Parameter: 4292 . M - pointer to place new matrix 4293 4294 Level: intermediate 4295 4296 Notes: 4297 `MatConvert()` first creates a new matrix and then copies the data from 4298 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4299 entries of one matrix to another already existing matrix context. 4300 4301 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4302 the MPI communicator of the generated matrix is always the same as the communicator 4303 of the input matrix. 4304 4305 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4306 @*/ 4307 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4308 { 4309 PetscBool sametype, issame, flg; 4310 PetscBool3 issymmetric, ishermitian; 4311 char convname[256], mtype[256]; 4312 Mat B; 4313 4314 PetscFunctionBegin; 4315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4316 PetscValidType(mat, 1); 4317 PetscAssertPointer(M, 4); 4318 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4319 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4320 MatCheckPreallocated(mat, 1); 4321 4322 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4323 if (flg) newtype = mtype; 4324 4325 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4326 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4327 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4328 if (reuse == MAT_REUSE_MATRIX) { 4329 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4330 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4331 } 4332 4333 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4334 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4335 PetscFunctionReturn(PETSC_SUCCESS); 4336 } 4337 4338 /* Cache Mat options because some converters use MatHeaderReplace */ 4339 issymmetric = mat->symmetric; 4340 ishermitian = mat->hermitian; 4341 4342 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4343 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4344 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4345 } else { 4346 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4347 const char *prefix[3] = {"seq", "mpi", ""}; 4348 PetscInt i; 4349 /* 4350 Order of precedence: 4351 0) See if newtype is a superclass of the current matrix. 4352 1) See if a specialized converter is known to the current matrix. 4353 2) See if a specialized converter is known to the desired matrix class. 4354 3) See if a good general converter is registered for the desired class 4355 (as of 6/27/03 only MATMPIADJ falls into this category). 4356 4) See if a good general converter is known for the current matrix. 4357 5) Use a really basic converter. 4358 */ 4359 4360 /* 0) See if newtype is a superclass of the current matrix. 4361 i.e mat is mpiaij and newtype is aij */ 4362 for (i = 0; i < 2; i++) { 4363 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4365 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4366 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4367 if (flg) { 4368 if (reuse == MAT_INPLACE_MATRIX) { 4369 PetscCall(PetscInfo(mat, "Early return\n")); 4370 PetscFunctionReturn(PETSC_SUCCESS); 4371 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4372 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4373 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4374 PetscFunctionReturn(PETSC_SUCCESS); 4375 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4376 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4377 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4378 PetscFunctionReturn(PETSC_SUCCESS); 4379 } 4380 } 4381 } 4382 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4383 for (i = 0; i < 3; i++) { 4384 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4385 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4386 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4387 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4388 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4389 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4390 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4391 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4392 if (conv) goto foundconv; 4393 } 4394 4395 /* 2) See if a specialized converter is known to the desired matrix class. */ 4396 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4397 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4398 PetscCall(MatSetType(B, newtype)); 4399 for (i = 0; i < 3; i++) { 4400 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4401 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4402 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4403 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4404 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4405 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4406 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4407 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4408 if (conv) { 4409 PetscCall(MatDestroy(&B)); 4410 goto foundconv; 4411 } 4412 } 4413 4414 /* 3) See if a good general converter is registered for the desired class */ 4415 conv = B->ops->convertfrom; 4416 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4417 PetscCall(MatDestroy(&B)); 4418 if (conv) goto foundconv; 4419 4420 /* 4) See if a good general converter is known for the current matrix */ 4421 if (mat->ops->convert) conv = mat->ops->convert; 4422 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4423 if (conv) goto foundconv; 4424 4425 /* 5) Use a really basic converter. */ 4426 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4427 conv = MatConvert_Basic; 4428 4429 foundconv: 4430 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4431 PetscCall((*conv)(mat, newtype, reuse, M)); 4432 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4433 /* the block sizes must be same if the mappings are copied over */ 4434 (*M)->rmap->bs = mat->rmap->bs; 4435 (*M)->cmap->bs = mat->cmap->bs; 4436 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4437 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4438 (*M)->rmap->mapping = mat->rmap->mapping; 4439 (*M)->cmap->mapping = mat->cmap->mapping; 4440 } 4441 (*M)->stencil.dim = mat->stencil.dim; 4442 (*M)->stencil.noc = mat->stencil.noc; 4443 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4444 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4445 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4446 } 4447 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4448 } 4449 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4450 4451 /* Copy Mat options */ 4452 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4453 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4454 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4455 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4456 PetscFunctionReturn(PETSC_SUCCESS); 4457 } 4458 4459 /*@C 4460 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4461 4462 Not Collective 4463 4464 Input Parameter: 4465 . mat - the matrix, must be a factored matrix 4466 4467 Output Parameter: 4468 . type - the string name of the package (do not free this string) 4469 4470 Level: intermediate 4471 4472 Fortran Note: 4473 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4474 4475 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4476 @*/ 4477 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4478 { 4479 PetscErrorCode (*conv)(Mat, MatSolverType *); 4480 4481 PetscFunctionBegin; 4482 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4483 PetscValidType(mat, 1); 4484 PetscAssertPointer(type, 2); 4485 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4486 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4487 if (conv) PetscCall((*conv)(mat, type)); 4488 else *type = MATSOLVERPETSC; 4489 PetscFunctionReturn(PETSC_SUCCESS); 4490 } 4491 4492 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4493 struct _MatSolverTypeForSpecifcType { 4494 MatType mtype; 4495 /* no entry for MAT_FACTOR_NONE */ 4496 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4497 MatSolverTypeForSpecifcType next; 4498 }; 4499 4500 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4501 struct _MatSolverTypeHolder { 4502 char *name; 4503 MatSolverTypeForSpecifcType handlers; 4504 MatSolverTypeHolder next; 4505 }; 4506 4507 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4508 4509 /*@C 4510 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4511 4512 Input Parameters: 4513 + package - name of the package, for example petsc or superlu 4514 . mtype - the matrix type that works with this package 4515 . ftype - the type of factorization supported by the package 4516 - createfactor - routine that will create the factored matrix ready to be used 4517 4518 Level: developer 4519 4520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4521 `MatGetFactor()` 4522 @*/ 4523 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4524 { 4525 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4526 PetscBool flg; 4527 MatSolverTypeForSpecifcType inext, iprev = NULL; 4528 4529 PetscFunctionBegin; 4530 PetscCall(MatInitializePackage()); 4531 if (!next) { 4532 PetscCall(PetscNew(&MatSolverTypeHolders)); 4533 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4534 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4535 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4536 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4537 PetscFunctionReturn(PETSC_SUCCESS); 4538 } 4539 while (next) { 4540 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4541 if (flg) { 4542 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4543 inext = next->handlers; 4544 while (inext) { 4545 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4546 if (flg) { 4547 inext->createfactor[(int)ftype - 1] = createfactor; 4548 PetscFunctionReturn(PETSC_SUCCESS); 4549 } 4550 iprev = inext; 4551 inext = inext->next; 4552 } 4553 PetscCall(PetscNew(&iprev->next)); 4554 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4555 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4556 PetscFunctionReturn(PETSC_SUCCESS); 4557 } 4558 prev = next; 4559 next = next->next; 4560 } 4561 PetscCall(PetscNew(&prev->next)); 4562 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4563 PetscCall(PetscNew(&prev->next->handlers)); 4564 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4565 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4566 PetscFunctionReturn(PETSC_SUCCESS); 4567 } 4568 4569 /*@C 4570 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4571 4572 Input Parameters: 4573 + 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 4574 . ftype - the type of factorization supported by the type 4575 - mtype - the matrix type that works with this type 4576 4577 Output Parameters: 4578 + foundtype - `PETSC_TRUE` if the type was registered 4579 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4580 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4581 4582 Calling sequence of `createfactor`: 4583 + A - the matrix providing the factor matrix 4584 . mtype - the `MatType` of the factor requested 4585 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4586 4587 Level: developer 4588 4589 Note: 4590 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4591 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4592 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4593 4594 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4595 `MatInitializePackage()` 4596 @*/ 4597 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4598 { 4599 MatSolverTypeHolder next = MatSolverTypeHolders; 4600 PetscBool flg; 4601 MatSolverTypeForSpecifcType inext; 4602 4603 PetscFunctionBegin; 4604 if (foundtype) *foundtype = PETSC_FALSE; 4605 if (foundmtype) *foundmtype = PETSC_FALSE; 4606 if (createfactor) *createfactor = NULL; 4607 4608 if (type) { 4609 while (next) { 4610 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4611 if (flg) { 4612 if (foundtype) *foundtype = PETSC_TRUE; 4613 inext = next->handlers; 4614 while (inext) { 4615 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4616 if (flg) { 4617 if (foundmtype) *foundmtype = PETSC_TRUE; 4618 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4619 PetscFunctionReturn(PETSC_SUCCESS); 4620 } 4621 inext = inext->next; 4622 } 4623 } 4624 next = next->next; 4625 } 4626 } else { 4627 while (next) { 4628 inext = next->handlers; 4629 while (inext) { 4630 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4631 if (flg && inext->createfactor[(int)ftype - 1]) { 4632 if (foundtype) *foundtype = PETSC_TRUE; 4633 if (foundmtype) *foundmtype = PETSC_TRUE; 4634 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4635 PetscFunctionReturn(PETSC_SUCCESS); 4636 } 4637 inext = inext->next; 4638 } 4639 next = next->next; 4640 } 4641 /* try with base classes inext->mtype */ 4642 next = MatSolverTypeHolders; 4643 while (next) { 4644 inext = next->handlers; 4645 while (inext) { 4646 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4647 if (flg && inext->createfactor[(int)ftype - 1]) { 4648 if (foundtype) *foundtype = PETSC_TRUE; 4649 if (foundmtype) *foundmtype = PETSC_TRUE; 4650 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4651 PetscFunctionReturn(PETSC_SUCCESS); 4652 } 4653 inext = inext->next; 4654 } 4655 next = next->next; 4656 } 4657 } 4658 PetscFunctionReturn(PETSC_SUCCESS); 4659 } 4660 4661 PetscErrorCode MatSolverTypeDestroy(void) 4662 { 4663 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4664 MatSolverTypeForSpecifcType inext, iprev; 4665 4666 PetscFunctionBegin; 4667 while (next) { 4668 PetscCall(PetscFree(next->name)); 4669 inext = next->handlers; 4670 while (inext) { 4671 PetscCall(PetscFree(inext->mtype)); 4672 iprev = inext; 4673 inext = inext->next; 4674 PetscCall(PetscFree(iprev)); 4675 } 4676 prev = next; 4677 next = next->next; 4678 PetscCall(PetscFree(prev)); 4679 } 4680 MatSolverTypeHolders = NULL; 4681 PetscFunctionReturn(PETSC_SUCCESS); 4682 } 4683 4684 /*@C 4685 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4686 4687 Logically Collective 4688 4689 Input Parameter: 4690 . mat - the matrix 4691 4692 Output Parameter: 4693 . flg - `PETSC_TRUE` if uses the ordering 4694 4695 Level: developer 4696 4697 Note: 4698 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4699 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4700 4701 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4702 @*/ 4703 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4704 { 4705 PetscFunctionBegin; 4706 *flg = mat->canuseordering; 4707 PetscFunctionReturn(PETSC_SUCCESS); 4708 } 4709 4710 /*@C 4711 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4712 4713 Logically Collective 4714 4715 Input Parameters: 4716 + mat - the matrix obtained with `MatGetFactor()` 4717 - ftype - the factorization type to be used 4718 4719 Output Parameter: 4720 . otype - the preferred ordering type 4721 4722 Level: developer 4723 4724 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4725 @*/ 4726 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4727 { 4728 PetscFunctionBegin; 4729 *otype = mat->preferredordering[ftype]; 4730 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4731 PetscFunctionReturn(PETSC_SUCCESS); 4732 } 4733 4734 /*@C 4735 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4736 4737 Collective 4738 4739 Input Parameters: 4740 + mat - the matrix 4741 . 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 4742 the other criteria is returned 4743 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4744 4745 Output Parameter: 4746 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4747 4748 Options Database Keys: 4749 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4750 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4751 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4752 4753 Level: intermediate 4754 4755 Notes: 4756 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4757 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4758 4759 Users usually access the factorization solvers via `KSP` 4760 4761 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4762 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 4763 4764 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4765 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4766 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4767 4768 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4769 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4770 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4771 4772 Developer Note: 4773 This should actually be called `MatCreateFactor()` since it creates a new factor object 4774 4775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4776 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4777 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4778 @*/ 4779 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4780 { 4781 PetscBool foundtype, foundmtype; 4782 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4783 4784 PetscFunctionBegin; 4785 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4786 PetscValidType(mat, 1); 4787 4788 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4789 MatCheckPreallocated(mat, 1); 4790 4791 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4792 if (!foundtype) { 4793 if (type) { 4794 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], 4795 ((PetscObject)mat)->type_name, type); 4796 } else { 4797 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); 4798 } 4799 } 4800 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4801 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); 4802 4803 PetscCall((*conv)(mat, ftype, f)); 4804 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4805 PetscFunctionReturn(PETSC_SUCCESS); 4806 } 4807 4808 /*@C 4809 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4810 4811 Not Collective 4812 4813 Input Parameters: 4814 + mat - the matrix 4815 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4816 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4817 4818 Output Parameter: 4819 . flg - PETSC_TRUE if the factorization is available 4820 4821 Level: intermediate 4822 4823 Notes: 4824 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4825 such as pastix, superlu, mumps etc. 4826 4827 PETSc must have been ./configure to use the external solver, using the option --download-package 4828 4829 Developer Note: 4830 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4831 4832 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4833 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4834 @*/ 4835 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4836 { 4837 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4838 4839 PetscFunctionBegin; 4840 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4841 PetscAssertPointer(flg, 4); 4842 4843 *flg = PETSC_FALSE; 4844 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4845 4846 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4847 MatCheckPreallocated(mat, 1); 4848 4849 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4850 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4851 PetscFunctionReturn(PETSC_SUCCESS); 4852 } 4853 4854 /*@ 4855 MatDuplicate - Duplicates a matrix including the non-zero structure. 4856 4857 Collective 4858 4859 Input Parameters: 4860 + mat - the matrix 4861 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4862 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4863 4864 Output Parameter: 4865 . M - pointer to place new matrix 4866 4867 Level: intermediate 4868 4869 Notes: 4870 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4871 4872 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4873 4874 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. 4875 4876 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4877 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4878 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4879 4880 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4881 @*/ 4882 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4883 { 4884 Mat B; 4885 VecType vtype; 4886 PetscInt i; 4887 PetscObject dm, container_h, container_d; 4888 void (*viewf)(void); 4889 4890 PetscFunctionBegin; 4891 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4892 PetscValidType(mat, 1); 4893 PetscAssertPointer(M, 3); 4894 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4895 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4896 MatCheckPreallocated(mat, 1); 4897 4898 *M = NULL; 4899 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4900 PetscUseTypeMethod(mat, duplicate, op, M); 4901 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4902 B = *M; 4903 4904 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4905 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4906 PetscCall(MatGetVecType(mat, &vtype)); 4907 PetscCall(MatSetVecType(B, vtype)); 4908 4909 B->stencil.dim = mat->stencil.dim; 4910 B->stencil.noc = mat->stencil.noc; 4911 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4912 B->stencil.dims[i] = mat->stencil.dims[i]; 4913 B->stencil.starts[i] = mat->stencil.starts[i]; 4914 } 4915 4916 B->nooffproczerorows = mat->nooffproczerorows; 4917 B->nooffprocentries = mat->nooffprocentries; 4918 4919 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4920 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4921 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4922 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4923 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4924 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4925 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4926 PetscFunctionReturn(PETSC_SUCCESS); 4927 } 4928 4929 /*@ 4930 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4931 4932 Logically Collective 4933 4934 Input Parameter: 4935 . mat - the matrix 4936 4937 Output Parameter: 4938 . v - the diagonal of the matrix 4939 4940 Level: intermediate 4941 4942 Note: 4943 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4944 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4945 is larger than `ndiag`, the values of the remaining entries are unspecified. 4946 4947 Currently only correct in parallel for square matrices. 4948 4949 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4950 @*/ 4951 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4952 { 4953 PetscFunctionBegin; 4954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4955 PetscValidType(mat, 1); 4956 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4957 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4958 MatCheckPreallocated(mat, 1); 4959 if (PetscDefined(USE_DEBUG)) { 4960 PetscInt nv, row, col, ndiag; 4961 4962 PetscCall(VecGetLocalSize(v, &nv)); 4963 PetscCall(MatGetLocalSize(mat, &row, &col)); 4964 ndiag = PetscMin(row, col); 4965 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); 4966 } 4967 4968 PetscUseTypeMethod(mat, getdiagonal, v); 4969 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4970 PetscFunctionReturn(PETSC_SUCCESS); 4971 } 4972 4973 /*@C 4974 MatGetRowMin - Gets the minimum value (of the real part) of each 4975 row of the matrix 4976 4977 Logically Collective 4978 4979 Input Parameter: 4980 . mat - the matrix 4981 4982 Output Parameters: 4983 + v - the vector for storing the maximums 4984 - idx - the indices of the column found for each row (optional) 4985 4986 Level: intermediate 4987 4988 Note: 4989 The result of this call are the same as if one converted the matrix to dense format 4990 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4991 4992 This code is only implemented for a couple of matrix formats. 4993 4994 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4995 `MatGetRowMax()` 4996 @*/ 4997 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4998 { 4999 PetscFunctionBegin; 5000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5001 PetscValidType(mat, 1); 5002 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5003 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5004 5005 if (!mat->cmap->N) { 5006 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5007 if (idx) { 5008 PetscInt i, m = mat->rmap->n; 5009 for (i = 0; i < m; i++) idx[i] = -1; 5010 } 5011 } else { 5012 MatCheckPreallocated(mat, 1); 5013 } 5014 PetscUseTypeMethod(mat, getrowmin, v, idx); 5015 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5016 PetscFunctionReturn(PETSC_SUCCESS); 5017 } 5018 5019 /*@C 5020 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5021 row of the matrix 5022 5023 Logically Collective 5024 5025 Input Parameter: 5026 . mat - the matrix 5027 5028 Output Parameters: 5029 + v - the vector for storing the minimums 5030 - idx - the indices of the column found for each row (or `NULL` if not needed) 5031 5032 Level: intermediate 5033 5034 Notes: 5035 if a row is completely empty or has only 0.0 values then the `idx` value for that 5036 row is 0 (the first column). 5037 5038 This code is only implemented for a couple of matrix formats. 5039 5040 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5041 @*/ 5042 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5043 { 5044 PetscFunctionBegin; 5045 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5046 PetscValidType(mat, 1); 5047 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5048 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5049 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5050 5051 if (!mat->cmap->N) { 5052 PetscCall(VecSet(v, 0.0)); 5053 if (idx) { 5054 PetscInt i, m = mat->rmap->n; 5055 for (i = 0; i < m; i++) idx[i] = -1; 5056 } 5057 } else { 5058 MatCheckPreallocated(mat, 1); 5059 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5060 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5061 } 5062 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5063 PetscFunctionReturn(PETSC_SUCCESS); 5064 } 5065 5066 /*@C 5067 MatGetRowMax - Gets the maximum value (of the real part) of each 5068 row of the matrix 5069 5070 Logically Collective 5071 5072 Input Parameter: 5073 . mat - the matrix 5074 5075 Output Parameters: 5076 + v - the vector for storing the maximums 5077 - idx - the indices of the column found for each row (optional) 5078 5079 Level: intermediate 5080 5081 Notes: 5082 The result of this call are the same as if one converted the matrix to dense format 5083 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5084 5085 This code is only implemented for a couple of matrix formats. 5086 5087 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5088 @*/ 5089 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5090 { 5091 PetscFunctionBegin; 5092 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5093 PetscValidType(mat, 1); 5094 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5096 5097 if (!mat->cmap->N) { 5098 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5099 if (idx) { 5100 PetscInt i, m = mat->rmap->n; 5101 for (i = 0; i < m; i++) idx[i] = -1; 5102 } 5103 } else { 5104 MatCheckPreallocated(mat, 1); 5105 PetscUseTypeMethod(mat, getrowmax, v, idx); 5106 } 5107 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5108 PetscFunctionReturn(PETSC_SUCCESS); 5109 } 5110 5111 /*@C 5112 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5113 row of the matrix 5114 5115 Logically Collective 5116 5117 Input Parameter: 5118 . mat - the matrix 5119 5120 Output Parameters: 5121 + v - the vector for storing the maximums 5122 - idx - the indices of the column found for each row (or `NULL` if not needed) 5123 5124 Level: intermediate 5125 5126 Notes: 5127 if a row is completely empty or has only 0.0 values then the `idx` value for that 5128 row is 0 (the first column). 5129 5130 This code is only implemented for a couple of matrix formats. 5131 5132 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5133 @*/ 5134 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5135 { 5136 PetscFunctionBegin; 5137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5138 PetscValidType(mat, 1); 5139 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5140 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5141 5142 if (!mat->cmap->N) { 5143 PetscCall(VecSet(v, 0.0)); 5144 if (idx) { 5145 PetscInt i, m = mat->rmap->n; 5146 for (i = 0; i < m; i++) idx[i] = -1; 5147 } 5148 } else { 5149 MatCheckPreallocated(mat, 1); 5150 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5151 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5152 } 5153 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5154 PetscFunctionReturn(PETSC_SUCCESS); 5155 } 5156 5157 /*@C 5158 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5159 5160 Logically Collective 5161 5162 Input Parameter: 5163 . mat - the matrix 5164 5165 Output Parameter: 5166 . v - the vector for storing the sum 5167 5168 Level: intermediate 5169 5170 This code is only implemented for a couple of matrix formats. 5171 5172 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5173 @*/ 5174 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5175 { 5176 PetscFunctionBegin; 5177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5178 PetscValidType(mat, 1); 5179 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5180 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5181 5182 if (!mat->cmap->N) { 5183 PetscCall(VecSet(v, 0.0)); 5184 } else { 5185 MatCheckPreallocated(mat, 1); 5186 PetscUseTypeMethod(mat, getrowsumabs, v); 5187 } 5188 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5189 PetscFunctionReturn(PETSC_SUCCESS); 5190 } 5191 5192 /*@ 5193 MatGetRowSum - Gets the sum of each row of the matrix 5194 5195 Logically or Neighborhood Collective 5196 5197 Input Parameter: 5198 . mat - the matrix 5199 5200 Output Parameter: 5201 . v - the vector for storing the sum of rows 5202 5203 Level: intermediate 5204 5205 Note: 5206 This code is slow since it is not currently specialized for different formats 5207 5208 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5209 @*/ 5210 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5211 { 5212 Vec ones; 5213 5214 PetscFunctionBegin; 5215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5216 PetscValidType(mat, 1); 5217 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5218 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5219 MatCheckPreallocated(mat, 1); 5220 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5221 PetscCall(VecSet(ones, 1.)); 5222 PetscCall(MatMult(mat, ones, v)); 5223 PetscCall(VecDestroy(&ones)); 5224 PetscFunctionReturn(PETSC_SUCCESS); 5225 } 5226 5227 /*@ 5228 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5229 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5230 5231 Collective 5232 5233 Input Parameter: 5234 . mat - the matrix to provide the transpose 5235 5236 Output Parameter: 5237 . 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 5238 5239 Level: advanced 5240 5241 Note: 5242 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 5243 routine allows bypassing that call. 5244 5245 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5246 @*/ 5247 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5248 { 5249 PetscContainer rB = NULL; 5250 MatParentState *rb = NULL; 5251 5252 PetscFunctionBegin; 5253 PetscCall(PetscNew(&rb)); 5254 rb->id = ((PetscObject)mat)->id; 5255 rb->state = 0; 5256 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5257 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5258 PetscCall(PetscContainerSetPointer(rB, rb)); 5259 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5260 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5261 PetscCall(PetscObjectDereference((PetscObject)rB)); 5262 PetscFunctionReturn(PETSC_SUCCESS); 5263 } 5264 5265 /*@ 5266 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5267 5268 Collective 5269 5270 Input Parameters: 5271 + mat - the matrix to transpose 5272 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5273 5274 Output Parameter: 5275 . B - the transpose 5276 5277 Level: intermediate 5278 5279 Notes: 5280 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5281 5282 `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 5283 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5284 5285 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. 5286 5287 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5288 5289 If mat is unchanged from the last call this function returns immediately without recomputing the result 5290 5291 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5292 5293 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5294 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5295 @*/ 5296 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5297 { 5298 PetscContainer rB = NULL; 5299 MatParentState *rb = NULL; 5300 5301 PetscFunctionBegin; 5302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5303 PetscValidType(mat, 1); 5304 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5305 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5306 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5307 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5308 MatCheckPreallocated(mat, 1); 5309 if (reuse == MAT_REUSE_MATRIX) { 5310 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5311 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5312 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5313 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5314 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5315 } 5316 5317 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5318 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5319 PetscUseTypeMethod(mat, transpose, reuse, B); 5320 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5321 } 5322 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5323 5324 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5325 if (reuse != MAT_INPLACE_MATRIX) { 5326 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5327 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5328 rb->state = ((PetscObject)mat)->state; 5329 rb->nonzerostate = mat->nonzerostate; 5330 } 5331 PetscFunctionReturn(PETSC_SUCCESS); 5332 } 5333 5334 /*@ 5335 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5336 5337 Collective 5338 5339 Input Parameter: 5340 . A - the matrix to transpose 5341 5342 Output Parameter: 5343 . 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 5344 numerical portion. 5345 5346 Level: intermediate 5347 5348 Note: 5349 This is not supported for many matrix types, use `MatTranspose()` in those cases 5350 5351 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5352 @*/ 5353 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5354 { 5355 PetscFunctionBegin; 5356 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5357 PetscValidType(A, 1); 5358 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5359 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5360 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5361 PetscUseTypeMethod(A, transposesymbolic, B); 5362 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5363 5364 PetscCall(MatTransposeSetPrecursor(A, *B)); 5365 PetscFunctionReturn(PETSC_SUCCESS); 5366 } 5367 5368 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5369 { 5370 PetscContainer rB; 5371 MatParentState *rb; 5372 5373 PetscFunctionBegin; 5374 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5375 PetscValidType(A, 1); 5376 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5377 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5378 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5379 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5380 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5381 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5382 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5383 PetscFunctionReturn(PETSC_SUCCESS); 5384 } 5385 5386 /*@ 5387 MatIsTranspose - Test whether a matrix is another one's transpose, 5388 or its own, in which case it tests symmetry. 5389 5390 Collective 5391 5392 Input Parameters: 5393 + A - the matrix to test 5394 . B - the matrix to test against, this can equal the first parameter 5395 - tol - tolerance, differences between entries smaller than this are counted as zero 5396 5397 Output Parameter: 5398 . flg - the result 5399 5400 Level: intermediate 5401 5402 Notes: 5403 Only available for `MATAIJ` matrices. 5404 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 Note: 6790 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6791 Layouts](sec_matlayout) for details on matrix layouts. 6792 6793 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6794 @*/ 6795 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6796 { 6797 PetscFunctionBegin; 6798 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6799 PetscValidType(mat, 1); 6800 if (m) PetscAssertPointer(m, 2); 6801 if (n) PetscAssertPointer(n, 3); 6802 MatCheckPreallocated(mat, 1); 6803 if (m) *m = mat->cmap->rstart; 6804 if (n) *n = mat->cmap->rend; 6805 PetscFunctionReturn(PETSC_SUCCESS); 6806 } 6807 6808 /*@C 6809 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6810 this MPI process. 6811 6812 Not Collective 6813 6814 Input Parameter: 6815 . mat - the matrix 6816 6817 Output Parameters: 6818 + m - the global index of the first local row, use `NULL` to not obtain this value 6819 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6820 6821 Level: beginner 6822 6823 Note: 6824 For all matrices it returns the range of matrix rows associated with rows of a vector that 6825 would contain the result of a matrix vector product with this matrix. See [Matrix 6826 Layouts](sec_matlayout) for details on matrix layouts. 6827 6828 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6829 `PetscLayout` 6830 @*/ 6831 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6832 { 6833 PetscFunctionBegin; 6834 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6835 PetscValidType(mat, 1); 6836 if (m) PetscAssertPointer(m, 2); 6837 if (n) PetscAssertPointer(n, 3); 6838 MatCheckPreallocated(mat, 1); 6839 if (m) *m = mat->rmap->rstart; 6840 if (n) *n = mat->rmap->rend; 6841 PetscFunctionReturn(PETSC_SUCCESS); 6842 } 6843 6844 /*@C 6845 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6846 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6847 6848 Not Collective, unless matrix has not been allocated 6849 6850 Input Parameter: 6851 . mat - the matrix 6852 6853 Output Parameter: 6854 . ranges - start of each processors portion plus one more than the total length at the end 6855 6856 Level: beginner 6857 6858 Note: 6859 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6860 would contain the result of a matrix vector product with this matrix. See [Matrix 6861 Layouts](sec_matlayout) for details on matrix layouts. 6862 6863 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6864 @*/ 6865 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6866 { 6867 PetscFunctionBegin; 6868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6869 PetscValidType(mat, 1); 6870 MatCheckPreallocated(mat, 1); 6871 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6872 PetscFunctionReturn(PETSC_SUCCESS); 6873 } 6874 6875 /*@C 6876 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6877 vector one multiplies this vector by that are owned by each processor. 6878 6879 Not Collective, unless matrix has not been allocated 6880 6881 Input Parameter: 6882 . mat - the matrix 6883 6884 Output Parameter: 6885 . ranges - start of each processors portion plus one more than the total length at the end 6886 6887 Level: beginner 6888 6889 Note: 6890 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6891 Layouts](sec_matlayout) for details on matrix layouts. 6892 6893 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6894 @*/ 6895 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6896 { 6897 PetscFunctionBegin; 6898 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6899 PetscValidType(mat, 1); 6900 MatCheckPreallocated(mat, 1); 6901 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6902 PetscFunctionReturn(PETSC_SUCCESS); 6903 } 6904 6905 /*@C 6906 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6907 6908 Not Collective 6909 6910 Input Parameter: 6911 . A - matrix 6912 6913 Output Parameters: 6914 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6915 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6916 6917 Level: intermediate 6918 6919 Note: 6920 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6921 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6922 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6923 details on matrix layouts. 6924 6925 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6926 @*/ 6927 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6928 { 6929 PetscErrorCode (*f)(Mat, IS *, IS *); 6930 6931 PetscFunctionBegin; 6932 MatCheckPreallocated(A, 1); 6933 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6934 if (f) { 6935 PetscCall((*f)(A, rows, cols)); 6936 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6937 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6938 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6939 } 6940 PetscFunctionReturn(PETSC_SUCCESS); 6941 } 6942 6943 /*@C 6944 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6945 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6946 to complete the factorization. 6947 6948 Collective 6949 6950 Input Parameters: 6951 + fact - the factorized matrix obtained with `MatGetFactor()` 6952 . mat - the matrix 6953 . row - row permutation 6954 . col - column permutation 6955 - info - structure containing 6956 .vb 6957 levels - number of levels of fill. 6958 expected fill - as ratio of original fill. 6959 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6960 missing diagonal entries) 6961 .ve 6962 6963 Level: developer 6964 6965 Notes: 6966 See [Matrix Factorization](sec_matfactor) for additional information. 6967 6968 Most users should employ the `KSP` interface for linear solvers 6969 instead of working directly with matrix algebra routines such as this. 6970 See, e.g., `KSPCreate()`. 6971 6972 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 6973 6974 Developer Note: 6975 The Fortran interface is not autogenerated as the 6976 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6977 6978 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6979 `MatGetOrdering()`, `MatFactorInfo` 6980 @*/ 6981 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6982 { 6983 PetscFunctionBegin; 6984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6985 PetscValidType(mat, 2); 6986 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6987 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6988 PetscAssertPointer(info, 5); 6989 PetscAssertPointer(fact, 1); 6990 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6991 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6992 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6993 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6994 MatCheckPreallocated(mat, 2); 6995 6996 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6997 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6998 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6999 PetscFunctionReturn(PETSC_SUCCESS); 7000 } 7001 7002 /*@C 7003 MatICCFactorSymbolic - Performs symbolic incomplete 7004 Cholesky factorization for a symmetric matrix. Use 7005 `MatCholeskyFactorNumeric()` to complete the factorization. 7006 7007 Collective 7008 7009 Input Parameters: 7010 + fact - the factorized matrix obtained with `MatGetFactor()` 7011 . mat - the matrix to be factored 7012 . perm - row and column permutation 7013 - info - structure containing 7014 .vb 7015 levels - number of levels of fill. 7016 expected fill - as ratio of original fill. 7017 .ve 7018 7019 Level: developer 7020 7021 Notes: 7022 Most users should employ the `KSP` interface for linear solvers 7023 instead of working directly with matrix algebra routines such as this. 7024 See, e.g., `KSPCreate()`. 7025 7026 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7027 7028 Developer Note: 7029 The Fortran interface is not autogenerated as the 7030 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7031 7032 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7033 @*/ 7034 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7035 { 7036 PetscFunctionBegin; 7037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7038 PetscValidType(mat, 2); 7039 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7040 PetscAssertPointer(info, 4); 7041 PetscAssertPointer(fact, 1); 7042 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7043 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7044 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7045 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7046 MatCheckPreallocated(mat, 2); 7047 7048 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7049 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7050 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7051 PetscFunctionReturn(PETSC_SUCCESS); 7052 } 7053 7054 /*@C 7055 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7056 points to an array of valid matrices, they may be reused to store the new 7057 submatrices. 7058 7059 Collective 7060 7061 Input Parameters: 7062 + mat - the matrix 7063 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7064 . irow - index set of rows to extract 7065 . icol - index set of columns to extract 7066 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7067 7068 Output Parameter: 7069 . submat - the array of submatrices 7070 7071 Level: advanced 7072 7073 Notes: 7074 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7075 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7076 to extract a parallel submatrix. 7077 7078 Some matrix types place restrictions on the row and column 7079 indices, such as that they be sorted or that they be equal to each other. 7080 7081 The index sets may not have duplicate entries. 7082 7083 When extracting submatrices from a parallel matrix, each processor can 7084 form a different submatrix by setting the rows and columns of its 7085 individual index sets according to the local submatrix desired. 7086 7087 When finished using the submatrices, the user should destroy 7088 them with `MatDestroySubMatrices()`. 7089 7090 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7091 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7092 7093 This routine creates the matrices in submat; you should NOT create them before 7094 calling it. It also allocates the array of matrix pointers submat. 7095 7096 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7097 request one row/column in a block, they must request all rows/columns that are in 7098 that block. For example, if the block size is 2 you cannot request just row 0 and 7099 column 0. 7100 7101 Fortran Note: 7102 The Fortran interface is slightly different from that given below; it 7103 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7104 7105 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7106 @*/ 7107 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7108 { 7109 PetscInt i; 7110 PetscBool eq; 7111 7112 PetscFunctionBegin; 7113 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7114 PetscValidType(mat, 1); 7115 if (n) { 7116 PetscAssertPointer(irow, 3); 7117 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7118 PetscAssertPointer(icol, 4); 7119 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7120 } 7121 PetscAssertPointer(submat, 6); 7122 if (n && scall == MAT_REUSE_MATRIX) { 7123 PetscAssertPointer(*submat, 6); 7124 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7125 } 7126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7127 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7128 MatCheckPreallocated(mat, 1); 7129 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7130 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7131 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7132 for (i = 0; i < n; i++) { 7133 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7134 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7135 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7136 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7137 if (mat->boundtocpu && mat->bindingpropagates) { 7138 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7139 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7140 } 7141 #endif 7142 } 7143 PetscFunctionReturn(PETSC_SUCCESS); 7144 } 7145 7146 /*@C 7147 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7148 7149 Collective 7150 7151 Input Parameters: 7152 + mat - the matrix 7153 . n - the number of submatrixes to be extracted 7154 . irow - index set of rows to extract 7155 . icol - index set of columns to extract 7156 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7157 7158 Output Parameter: 7159 . submat - the array of submatrices 7160 7161 Level: advanced 7162 7163 Note: 7164 This is used by `PCGASM` 7165 7166 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7167 @*/ 7168 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7169 { 7170 PetscInt i; 7171 PetscBool eq; 7172 7173 PetscFunctionBegin; 7174 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7175 PetscValidType(mat, 1); 7176 if (n) { 7177 PetscAssertPointer(irow, 3); 7178 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7179 PetscAssertPointer(icol, 4); 7180 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7181 } 7182 PetscAssertPointer(submat, 6); 7183 if (n && scall == MAT_REUSE_MATRIX) { 7184 PetscAssertPointer(*submat, 6); 7185 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7186 } 7187 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7188 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7189 MatCheckPreallocated(mat, 1); 7190 7191 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7192 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7193 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7194 for (i = 0; i < n; i++) { 7195 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7196 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7197 } 7198 PetscFunctionReturn(PETSC_SUCCESS); 7199 } 7200 7201 /*@C 7202 MatDestroyMatrices - Destroys an array of matrices. 7203 7204 Collective 7205 7206 Input Parameters: 7207 + n - the number of local matrices 7208 - mat - the matrices (this is a pointer to the array of matrices) 7209 7210 Level: advanced 7211 7212 Note: 7213 Frees not only the matrices, but also the array that contains the matrices 7214 7215 Fortran Note: 7216 This does not free the array. 7217 7218 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7219 @*/ 7220 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7221 { 7222 PetscInt i; 7223 7224 PetscFunctionBegin; 7225 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7226 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7227 PetscAssertPointer(mat, 2); 7228 7229 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7230 7231 /* memory is allocated even if n = 0 */ 7232 PetscCall(PetscFree(*mat)); 7233 PetscFunctionReturn(PETSC_SUCCESS); 7234 } 7235 7236 /*@C 7237 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7238 7239 Collective 7240 7241 Input Parameters: 7242 + n - the number of local matrices 7243 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7244 sequence of `MatCreateSubMatrices()`) 7245 7246 Level: advanced 7247 7248 Note: 7249 Frees not only the matrices, but also the array that contains the matrices 7250 7251 Fortran Note: 7252 This does not free the array. 7253 7254 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7255 @*/ 7256 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7257 { 7258 Mat mat0; 7259 7260 PetscFunctionBegin; 7261 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7262 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7263 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7264 PetscAssertPointer(mat, 2); 7265 7266 mat0 = (*mat)[0]; 7267 if (mat0 && mat0->ops->destroysubmatrices) { 7268 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7269 } else { 7270 PetscCall(MatDestroyMatrices(n, mat)); 7271 } 7272 PetscFunctionReturn(PETSC_SUCCESS); 7273 } 7274 7275 /*@C 7276 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7277 7278 Collective 7279 7280 Input Parameter: 7281 . mat - the matrix 7282 7283 Output Parameter: 7284 . matstruct - the sequential matrix with the nonzero structure of mat 7285 7286 Level: developer 7287 7288 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7289 @*/ 7290 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7291 { 7292 PetscFunctionBegin; 7293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7294 PetscAssertPointer(matstruct, 2); 7295 7296 PetscValidType(mat, 1); 7297 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7298 MatCheckPreallocated(mat, 1); 7299 7300 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7301 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7302 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7303 PetscFunctionReturn(PETSC_SUCCESS); 7304 } 7305 7306 /*@C 7307 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7308 7309 Collective 7310 7311 Input Parameter: 7312 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7313 sequence of `MatGetSeqNonzeroStructure()`) 7314 7315 Level: advanced 7316 7317 Note: 7318 Frees not only the matrices, but also the array that contains the matrices 7319 7320 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7321 @*/ 7322 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7323 { 7324 PetscFunctionBegin; 7325 PetscAssertPointer(mat, 1); 7326 PetscCall(MatDestroy(mat)); 7327 PetscFunctionReturn(PETSC_SUCCESS); 7328 } 7329 7330 /*@ 7331 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7332 replaces the index sets by larger ones that represent submatrices with 7333 additional overlap. 7334 7335 Collective 7336 7337 Input Parameters: 7338 + mat - the matrix 7339 . n - the number of index sets 7340 . is - the array of index sets (these index sets will changed during the call) 7341 - ov - the additional overlap requested 7342 7343 Options Database Key: 7344 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7345 7346 Level: developer 7347 7348 Note: 7349 The computed overlap preserves the matrix block sizes when the blocks are square. 7350 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7351 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7352 7353 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7354 @*/ 7355 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7356 { 7357 PetscInt i, bs, cbs; 7358 7359 PetscFunctionBegin; 7360 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7361 PetscValidType(mat, 1); 7362 PetscValidLogicalCollectiveInt(mat, n, 2); 7363 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7364 if (n) { 7365 PetscAssertPointer(is, 3); 7366 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7367 } 7368 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7369 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7370 MatCheckPreallocated(mat, 1); 7371 7372 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7373 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7374 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7375 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7376 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7377 if (bs == cbs) { 7378 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7379 } 7380 PetscFunctionReturn(PETSC_SUCCESS); 7381 } 7382 7383 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7384 7385 /*@ 7386 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7387 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7388 additional overlap. 7389 7390 Collective 7391 7392 Input Parameters: 7393 + mat - the matrix 7394 . n - the number of index sets 7395 . is - the array of index sets (these index sets will changed during the call) 7396 - ov - the additional overlap requested 7397 7398 ` Options Database Key: 7399 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7400 7401 Level: developer 7402 7403 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7404 @*/ 7405 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7406 { 7407 PetscInt i; 7408 7409 PetscFunctionBegin; 7410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7411 PetscValidType(mat, 1); 7412 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7413 if (n) { 7414 PetscAssertPointer(is, 3); 7415 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7416 } 7417 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7418 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7419 MatCheckPreallocated(mat, 1); 7420 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7421 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7422 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7423 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7424 PetscFunctionReturn(PETSC_SUCCESS); 7425 } 7426 7427 /*@ 7428 MatGetBlockSize - Returns the matrix block size. 7429 7430 Not Collective 7431 7432 Input Parameter: 7433 . mat - the matrix 7434 7435 Output Parameter: 7436 . bs - block size 7437 7438 Level: intermediate 7439 7440 Notes: 7441 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7442 7443 If the block size has not been set yet this routine returns 1. 7444 7445 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7446 @*/ 7447 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7448 { 7449 PetscFunctionBegin; 7450 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7451 PetscAssertPointer(bs, 2); 7452 *bs = PetscAbs(mat->rmap->bs); 7453 PetscFunctionReturn(PETSC_SUCCESS); 7454 } 7455 7456 /*@ 7457 MatGetBlockSizes - Returns the matrix block row and column sizes. 7458 7459 Not Collective 7460 7461 Input Parameter: 7462 . mat - the matrix 7463 7464 Output Parameters: 7465 + rbs - row block size 7466 - cbs - column block size 7467 7468 Level: intermediate 7469 7470 Notes: 7471 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7472 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7473 7474 If a block size has not been set yet this routine returns 1. 7475 7476 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7477 @*/ 7478 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7479 { 7480 PetscFunctionBegin; 7481 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7482 if (rbs) PetscAssertPointer(rbs, 2); 7483 if (cbs) PetscAssertPointer(cbs, 3); 7484 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7485 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7486 PetscFunctionReturn(PETSC_SUCCESS); 7487 } 7488 7489 /*@ 7490 MatSetBlockSize - Sets the matrix block size. 7491 7492 Logically Collective 7493 7494 Input Parameters: 7495 + mat - the matrix 7496 - bs - block size 7497 7498 Level: intermediate 7499 7500 Notes: 7501 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7502 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7503 7504 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7505 is compatible with the matrix local sizes. 7506 7507 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7508 @*/ 7509 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7510 { 7511 PetscFunctionBegin; 7512 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7513 PetscValidLogicalCollectiveInt(mat, bs, 2); 7514 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7515 PetscFunctionReturn(PETSC_SUCCESS); 7516 } 7517 7518 typedef struct { 7519 PetscInt n; 7520 IS *is; 7521 Mat *mat; 7522 PetscObjectState nonzerostate; 7523 Mat C; 7524 } EnvelopeData; 7525 7526 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7527 { 7528 EnvelopeData *edata = (EnvelopeData *)ptr; 7529 7530 PetscFunctionBegin; 7531 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7532 PetscCall(PetscFree(edata->is)); 7533 PetscCall(PetscFree(edata)); 7534 PetscFunctionReturn(PETSC_SUCCESS); 7535 } 7536 7537 /*@ 7538 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7539 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7540 7541 Collective 7542 7543 Input Parameter: 7544 . mat - the matrix 7545 7546 Level: intermediate 7547 7548 Notes: 7549 There can be zeros within the blocks 7550 7551 The blocks can overlap between processes, including laying on more than two processes 7552 7553 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7554 @*/ 7555 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7556 { 7557 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7558 PetscInt *diag, *odiag, sc; 7559 VecScatter scatter; 7560 PetscScalar *seqv; 7561 const PetscScalar *parv; 7562 const PetscInt *ia, *ja; 7563 PetscBool set, flag, done; 7564 Mat AA = mat, A; 7565 MPI_Comm comm; 7566 PetscMPIInt rank, size, tag; 7567 MPI_Status status; 7568 PetscContainer container; 7569 EnvelopeData *edata; 7570 Vec seq, par; 7571 IS isglobal; 7572 7573 PetscFunctionBegin; 7574 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7575 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7576 if (!set || !flag) { 7577 /* TODO: only needs nonzero structure of transpose */ 7578 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7579 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7580 } 7581 PetscCall(MatAIJGetLocalMat(AA, &A)); 7582 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7583 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7584 7585 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7586 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7587 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7588 PetscCallMPI(MPI_Comm_size(comm, &size)); 7589 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7590 7591 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7592 7593 if (rank > 0) { 7594 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7595 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7596 } 7597 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7598 for (i = 0; i < n; i++) { 7599 env = PetscMax(env, ja[ia[i + 1] - 1]); 7600 II = rstart + i; 7601 if (env == II) { 7602 starts[lblocks] = tbs; 7603 sizes[lblocks++] = 1 + II - tbs; 7604 tbs = 1 + II; 7605 } 7606 } 7607 if (rank < size - 1) { 7608 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7609 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7610 } 7611 7612 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7613 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7614 PetscCall(MatDestroy(&A)); 7615 7616 PetscCall(PetscNew(&edata)); 7617 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7618 edata->n = lblocks; 7619 /* create IS needed for extracting blocks from the original matrix */ 7620 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7621 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7622 7623 /* Create the resulting inverse matrix structure with preallocation information */ 7624 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7625 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7626 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7627 PetscCall(MatSetType(edata->C, MATAIJ)); 7628 7629 /* Communicate the start and end of each row, from each block to the correct rank */ 7630 /* TODO: Use PetscSF instead of VecScatter */ 7631 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7632 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7633 PetscCall(VecGetArrayWrite(seq, &seqv)); 7634 for (PetscInt i = 0; i < lblocks; i++) { 7635 for (PetscInt j = 0; j < sizes[i]; j++) { 7636 seqv[cnt] = starts[i]; 7637 seqv[cnt + 1] = starts[i] + sizes[i]; 7638 cnt += 2; 7639 } 7640 } 7641 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7642 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7643 sc -= cnt; 7644 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7645 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7646 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7647 PetscCall(ISDestroy(&isglobal)); 7648 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7649 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7650 PetscCall(VecScatterDestroy(&scatter)); 7651 PetscCall(VecDestroy(&seq)); 7652 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7653 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7654 PetscCall(VecGetArrayRead(par, &parv)); 7655 cnt = 0; 7656 PetscCall(MatGetSize(mat, NULL, &n)); 7657 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7658 PetscInt start, end, d = 0, od = 0; 7659 7660 start = (PetscInt)PetscRealPart(parv[cnt]); 7661 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7662 cnt += 2; 7663 7664 if (start < cstart) { 7665 od += cstart - start + n - cend; 7666 d += cend - cstart; 7667 } else if (start < cend) { 7668 od += n - cend; 7669 d += cend - start; 7670 } else od += n - start; 7671 if (end <= cstart) { 7672 od -= cstart - end + n - cend; 7673 d -= cend - cstart; 7674 } else if (end < cend) { 7675 od -= n - cend; 7676 d -= cend - end; 7677 } else od -= n - end; 7678 7679 odiag[i] = od; 7680 diag[i] = d; 7681 } 7682 PetscCall(VecRestoreArrayRead(par, &parv)); 7683 PetscCall(VecDestroy(&par)); 7684 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7685 PetscCall(PetscFree2(diag, odiag)); 7686 PetscCall(PetscFree2(sizes, starts)); 7687 7688 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7689 PetscCall(PetscContainerSetPointer(container, edata)); 7690 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7691 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7692 PetscCall(PetscObjectDereference((PetscObject)container)); 7693 PetscFunctionReturn(PETSC_SUCCESS); 7694 } 7695 7696 /*@ 7697 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7698 7699 Collective 7700 7701 Input Parameters: 7702 + A - the matrix 7703 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7704 7705 Output Parameter: 7706 . C - matrix with inverted block diagonal of `A` 7707 7708 Level: advanced 7709 7710 Note: 7711 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7712 7713 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7714 @*/ 7715 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7716 { 7717 PetscContainer container; 7718 EnvelopeData *edata; 7719 PetscObjectState nonzerostate; 7720 7721 PetscFunctionBegin; 7722 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7723 if (!container) { 7724 PetscCall(MatComputeVariableBlockEnvelope(A)); 7725 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7726 } 7727 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7728 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7729 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7730 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7731 7732 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7733 *C = edata->C; 7734 7735 for (PetscInt i = 0; i < edata->n; i++) { 7736 Mat D; 7737 PetscScalar *dvalues; 7738 7739 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7740 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7741 PetscCall(MatSeqDenseInvert(D)); 7742 PetscCall(MatDenseGetArray(D, &dvalues)); 7743 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7744 PetscCall(MatDestroy(&D)); 7745 } 7746 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7747 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7748 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7749 PetscFunctionReturn(PETSC_SUCCESS); 7750 } 7751 7752 /*@ 7753 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7754 7755 Logically Collective 7756 7757 Input Parameters: 7758 + mat - the matrix 7759 . nblocks - the number of blocks on this process, each block can only exist on a single process 7760 - bsizes - the block sizes 7761 7762 Level: intermediate 7763 7764 Notes: 7765 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7766 7767 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. 7768 7769 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7770 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7771 @*/ 7772 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7773 { 7774 PetscInt i, ncnt = 0, nlocal; 7775 7776 PetscFunctionBegin; 7777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7778 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7779 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); 7780 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7781 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); 7782 PetscCall(PetscFree(mat->bsizes)); 7783 mat->nblocks = nblocks; 7784 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7785 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7786 PetscFunctionReturn(PETSC_SUCCESS); 7787 } 7788 7789 /*@C 7790 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7791 7792 Logically Collective; No Fortran Support 7793 7794 Input Parameter: 7795 . mat - the matrix 7796 7797 Output Parameters: 7798 + nblocks - the number of blocks on this process 7799 - bsizes - the block sizes 7800 7801 Level: intermediate 7802 7803 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7804 @*/ 7805 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7806 { 7807 PetscFunctionBegin; 7808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7809 *nblocks = mat->nblocks; 7810 *bsizes = mat->bsizes; 7811 PetscFunctionReturn(PETSC_SUCCESS); 7812 } 7813 7814 /*@ 7815 MatSetBlockSizes - Sets the matrix block row and column sizes. 7816 7817 Logically Collective 7818 7819 Input Parameters: 7820 + mat - the matrix 7821 . rbs - row block size 7822 - cbs - column block size 7823 7824 Level: intermediate 7825 7826 Notes: 7827 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7828 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7829 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7830 7831 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7832 are compatible with the matrix local sizes. 7833 7834 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7835 7836 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7837 @*/ 7838 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7839 { 7840 PetscFunctionBegin; 7841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7842 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7843 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7844 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7845 if (mat->rmap->refcnt) { 7846 ISLocalToGlobalMapping l2g = NULL; 7847 PetscLayout nmap = NULL; 7848 7849 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7850 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7851 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7852 mat->rmap = nmap; 7853 mat->rmap->mapping = l2g; 7854 } 7855 if (mat->cmap->refcnt) { 7856 ISLocalToGlobalMapping l2g = NULL; 7857 PetscLayout nmap = NULL; 7858 7859 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7860 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7861 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7862 mat->cmap = nmap; 7863 mat->cmap->mapping = l2g; 7864 } 7865 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7866 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7867 PetscFunctionReturn(PETSC_SUCCESS); 7868 } 7869 7870 /*@ 7871 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7872 7873 Logically Collective 7874 7875 Input Parameters: 7876 + mat - the matrix 7877 . fromRow - matrix from which to copy row block size 7878 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7879 7880 Level: developer 7881 7882 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7883 @*/ 7884 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7885 { 7886 PetscFunctionBegin; 7887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7888 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7889 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7890 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7891 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7892 PetscFunctionReturn(PETSC_SUCCESS); 7893 } 7894 7895 /*@ 7896 MatResidual - Default routine to calculate the residual r = b - Ax 7897 7898 Collective 7899 7900 Input Parameters: 7901 + mat - the matrix 7902 . b - the right-hand-side 7903 - x - the approximate solution 7904 7905 Output Parameter: 7906 . r - location to store the residual 7907 7908 Level: developer 7909 7910 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7911 @*/ 7912 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7913 { 7914 PetscFunctionBegin; 7915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7916 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7917 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7918 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7919 PetscValidType(mat, 1); 7920 MatCheckPreallocated(mat, 1); 7921 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7922 if (!mat->ops->residual) { 7923 PetscCall(MatMult(mat, x, r)); 7924 PetscCall(VecAYPX(r, -1.0, b)); 7925 } else { 7926 PetscUseTypeMethod(mat, residual, b, x, r); 7927 } 7928 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7929 PetscFunctionReturn(PETSC_SUCCESS); 7930 } 7931 7932 /*MC 7933 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7934 7935 Synopsis: 7936 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7937 7938 Not Collective 7939 7940 Input Parameters: 7941 + A - the matrix 7942 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7943 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7944 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7945 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7946 always used. 7947 7948 Output Parameters: 7949 + n - number of local rows in the (possibly compressed) matrix 7950 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7951 . ja - the column indices 7952 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7953 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7954 7955 Level: developer 7956 7957 Note: 7958 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7959 7960 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7961 M*/ 7962 7963 /*MC 7964 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7965 7966 Synopsis: 7967 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7968 7969 Not Collective 7970 7971 Input Parameters: 7972 + A - the matrix 7973 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7974 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7975 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7976 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7977 always used. 7978 . n - number of local rows in the (possibly compressed) matrix 7979 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7980 . ja - the column indices 7981 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7982 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7983 7984 Level: developer 7985 7986 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7987 M*/ 7988 7989 /*@C 7990 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7991 7992 Collective 7993 7994 Input Parameters: 7995 + mat - the matrix 7996 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7997 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7998 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7999 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8000 always used. 8001 8002 Output Parameters: 8003 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8004 . 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 8005 . ja - the column indices, use `NULL` if not needed 8006 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8007 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8008 8009 Level: developer 8010 8011 Notes: 8012 You CANNOT change any of the ia[] or ja[] values. 8013 8014 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8015 8016 Fortran Notes: 8017 Use 8018 .vb 8019 PetscInt, pointer :: ia(:),ja(:) 8020 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8021 ! Access the ith and jth entries via ia(i) and ja(j) 8022 .ve 8023 8024 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8025 8026 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8027 @*/ 8028 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8029 { 8030 PetscFunctionBegin; 8031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8032 PetscValidType(mat, 1); 8033 if (n) PetscAssertPointer(n, 5); 8034 if (ia) PetscAssertPointer(ia, 6); 8035 if (ja) PetscAssertPointer(ja, 7); 8036 if (done) PetscAssertPointer(done, 8); 8037 MatCheckPreallocated(mat, 1); 8038 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8039 else { 8040 if (done) *done = PETSC_TRUE; 8041 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8042 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8043 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8044 } 8045 PetscFunctionReturn(PETSC_SUCCESS); 8046 } 8047 8048 /*@C 8049 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8050 8051 Collective 8052 8053 Input Parameters: 8054 + mat - the matrix 8055 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8056 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8057 symmetrized 8058 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8059 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8060 always used. 8061 . n - number of columns in the (possibly compressed) matrix 8062 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8063 - ja - the row indices 8064 8065 Output Parameter: 8066 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8067 8068 Level: developer 8069 8070 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8071 @*/ 8072 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8073 { 8074 PetscFunctionBegin; 8075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8076 PetscValidType(mat, 1); 8077 PetscAssertPointer(n, 5); 8078 if (ia) PetscAssertPointer(ia, 6); 8079 if (ja) PetscAssertPointer(ja, 7); 8080 PetscAssertPointer(done, 8); 8081 MatCheckPreallocated(mat, 1); 8082 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8083 else { 8084 *done = PETSC_TRUE; 8085 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8086 } 8087 PetscFunctionReturn(PETSC_SUCCESS); 8088 } 8089 8090 /*@C 8091 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8092 8093 Collective 8094 8095 Input Parameters: 8096 + mat - the matrix 8097 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8098 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8099 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8100 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8101 always used. 8102 . n - size of (possibly compressed) matrix 8103 . ia - the row pointers 8104 - ja - the column indices 8105 8106 Output Parameter: 8107 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8108 8109 Level: developer 8110 8111 Note: 8112 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8113 us of the array after it has been restored. If you pass `NULL`, it will 8114 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8115 8116 Fortran Note: 8117 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8118 8119 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8120 @*/ 8121 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8122 { 8123 PetscFunctionBegin; 8124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8125 PetscValidType(mat, 1); 8126 if (ia) PetscAssertPointer(ia, 6); 8127 if (ja) PetscAssertPointer(ja, 7); 8128 if (done) PetscAssertPointer(done, 8); 8129 MatCheckPreallocated(mat, 1); 8130 8131 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8132 else { 8133 if (done) *done = PETSC_TRUE; 8134 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8135 if (n) *n = 0; 8136 if (ia) *ia = NULL; 8137 if (ja) *ja = NULL; 8138 } 8139 PetscFunctionReturn(PETSC_SUCCESS); 8140 } 8141 8142 /*@C 8143 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8144 8145 Collective 8146 8147 Input Parameters: 8148 + mat - the matrix 8149 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8150 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8151 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8152 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8153 always used. 8154 8155 Output Parameters: 8156 + n - size of (possibly compressed) matrix 8157 . ia - the column pointers 8158 . ja - the row indices 8159 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8160 8161 Level: developer 8162 8163 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8164 @*/ 8165 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8166 { 8167 PetscFunctionBegin; 8168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8169 PetscValidType(mat, 1); 8170 if (ia) PetscAssertPointer(ia, 6); 8171 if (ja) PetscAssertPointer(ja, 7); 8172 PetscAssertPointer(done, 8); 8173 MatCheckPreallocated(mat, 1); 8174 8175 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8176 else { 8177 *done = PETSC_TRUE; 8178 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8179 if (n) *n = 0; 8180 if (ia) *ia = NULL; 8181 if (ja) *ja = NULL; 8182 } 8183 PetscFunctionReturn(PETSC_SUCCESS); 8184 } 8185 8186 /*@C 8187 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8188 `MatGetColumnIJ()`. 8189 8190 Collective 8191 8192 Input Parameters: 8193 + mat - the matrix 8194 . ncolors - maximum color value 8195 . n - number of entries in colorarray 8196 - colorarray - array indicating color for each column 8197 8198 Output Parameter: 8199 . iscoloring - coloring generated using colorarray information 8200 8201 Level: developer 8202 8203 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8204 @*/ 8205 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8206 { 8207 PetscFunctionBegin; 8208 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8209 PetscValidType(mat, 1); 8210 PetscAssertPointer(colorarray, 4); 8211 PetscAssertPointer(iscoloring, 5); 8212 MatCheckPreallocated(mat, 1); 8213 8214 if (!mat->ops->coloringpatch) { 8215 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8216 } else { 8217 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8218 } 8219 PetscFunctionReturn(PETSC_SUCCESS); 8220 } 8221 8222 /*@ 8223 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8224 8225 Logically Collective 8226 8227 Input Parameter: 8228 . mat - the factored matrix to be reset 8229 8230 Level: developer 8231 8232 Notes: 8233 This routine should be used only with factored matrices formed by in-place 8234 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8235 format). This option can save memory, for example, when solving nonlinear 8236 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8237 ILU(0) preconditioner. 8238 8239 One can specify in-place ILU(0) factorization by calling 8240 .vb 8241 PCType(pc,PCILU); 8242 PCFactorSeUseInPlace(pc); 8243 .ve 8244 or by using the options -pc_type ilu -pc_factor_in_place 8245 8246 In-place factorization ILU(0) can also be used as a local 8247 solver for the blocks within the block Jacobi or additive Schwarz 8248 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8249 for details on setting local solver options. 8250 8251 Most users should employ the `KSP` interface for linear solvers 8252 instead of working directly with matrix algebra routines such as this. 8253 See, e.g., `KSPCreate()`. 8254 8255 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8256 @*/ 8257 PetscErrorCode MatSetUnfactored(Mat mat) 8258 { 8259 PetscFunctionBegin; 8260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8261 PetscValidType(mat, 1); 8262 MatCheckPreallocated(mat, 1); 8263 mat->factortype = MAT_FACTOR_NONE; 8264 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8265 PetscUseTypeMethod(mat, setunfactored); 8266 PetscFunctionReturn(PETSC_SUCCESS); 8267 } 8268 8269 /*MC 8270 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8271 8272 Synopsis: 8273 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8274 8275 Not Collective 8276 8277 Input Parameter: 8278 . x - matrix 8279 8280 Output Parameters: 8281 + xx_v - the Fortran pointer to the array 8282 - ierr - error code 8283 8284 Example of Usage: 8285 .vb 8286 PetscScalar, pointer xx_v(:,:) 8287 .... 8288 call MatDenseGetArrayF90(x,xx_v,ierr) 8289 a = xx_v(3) 8290 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8291 .ve 8292 8293 Level: advanced 8294 8295 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8296 M*/ 8297 8298 /*MC 8299 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8300 accessed with `MatDenseGetArrayF90()`. 8301 8302 Synopsis: 8303 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8304 8305 Not Collective 8306 8307 Input Parameters: 8308 + x - matrix 8309 - xx_v - the Fortran90 pointer to the array 8310 8311 Output Parameter: 8312 . ierr - error code 8313 8314 Example of Usage: 8315 .vb 8316 PetscScalar, pointer xx_v(:,:) 8317 .... 8318 call MatDenseGetArrayF90(x,xx_v,ierr) 8319 a = xx_v(3) 8320 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8321 .ve 8322 8323 Level: advanced 8324 8325 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8326 M*/ 8327 8328 /*MC 8329 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8330 8331 Synopsis: 8332 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8333 8334 Not Collective 8335 8336 Input Parameter: 8337 . x - matrix 8338 8339 Output Parameters: 8340 + xx_v - the Fortran pointer to the array 8341 - ierr - error code 8342 8343 Example of Usage: 8344 .vb 8345 PetscScalar, pointer xx_v(:) 8346 .... 8347 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8348 a = xx_v(3) 8349 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8350 .ve 8351 8352 Level: advanced 8353 8354 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8355 M*/ 8356 8357 /*MC 8358 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8359 accessed with `MatSeqAIJGetArrayF90()`. 8360 8361 Synopsis: 8362 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8363 8364 Not Collective 8365 8366 Input Parameters: 8367 + x - matrix 8368 - xx_v - the Fortran90 pointer to the array 8369 8370 Output Parameter: 8371 . ierr - error code 8372 8373 Example of Usage: 8374 .vb 8375 PetscScalar, pointer xx_v(:) 8376 .... 8377 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8378 a = xx_v(3) 8379 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8380 .ve 8381 8382 Level: advanced 8383 8384 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8385 M*/ 8386 8387 /*@ 8388 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8389 as the original matrix. 8390 8391 Collective 8392 8393 Input Parameters: 8394 + mat - the original matrix 8395 . isrow - parallel `IS` containing the rows this processor should obtain 8396 . 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. 8397 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8398 8399 Output Parameter: 8400 . newmat - the new submatrix, of the same type as the original matrix 8401 8402 Level: advanced 8403 8404 Notes: 8405 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8406 8407 Some matrix types place restrictions on the row and column indices, such 8408 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; 8409 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8410 8411 The index sets may not have duplicate entries. 8412 8413 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8414 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8415 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8416 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8417 you are finished using it. 8418 8419 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8420 the input matrix. 8421 8422 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8423 8424 If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature 8425 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8426 8427 Example usage: 8428 Consider the following 8x8 matrix with 34 non-zero values, that is 8429 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8430 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8431 as follows 8432 .vb 8433 1 2 0 | 0 3 0 | 0 4 8434 Proc0 0 5 6 | 7 0 0 | 8 0 8435 9 0 10 | 11 0 0 | 12 0 8436 ------------------------------------- 8437 13 0 14 | 15 16 17 | 0 0 8438 Proc1 0 18 0 | 19 20 21 | 0 0 8439 0 0 0 | 22 23 0 | 24 0 8440 ------------------------------------- 8441 Proc2 25 26 27 | 0 0 28 | 29 0 8442 30 0 0 | 31 32 33 | 0 34 8443 .ve 8444 8445 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8446 8447 .vb 8448 2 0 | 0 3 0 | 0 8449 Proc0 5 6 | 7 0 0 | 8 8450 ------------------------------- 8451 Proc1 18 0 | 19 20 21 | 0 8452 ------------------------------- 8453 Proc2 26 27 | 0 0 28 | 29 8454 0 0 | 31 32 33 | 0 8455 .ve 8456 8457 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8458 @*/ 8459 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8460 { 8461 PetscMPIInt size; 8462 Mat *local; 8463 IS iscoltmp; 8464 PetscBool flg; 8465 8466 PetscFunctionBegin; 8467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8468 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8469 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8470 PetscAssertPointer(newmat, 5); 8471 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8472 PetscValidType(mat, 1); 8473 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8474 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8475 8476 MatCheckPreallocated(mat, 1); 8477 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8478 8479 if (!iscol || isrow == iscol) { 8480 PetscBool stride; 8481 PetscMPIInt grabentirematrix = 0, grab; 8482 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8483 if (stride) { 8484 PetscInt first, step, n, rstart, rend; 8485 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8486 if (step == 1) { 8487 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8488 if (rstart == first) { 8489 PetscCall(ISGetLocalSize(isrow, &n)); 8490 if (n == rend - rstart) grabentirematrix = 1; 8491 } 8492 } 8493 } 8494 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8495 if (grab) { 8496 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8497 if (cll == MAT_INITIAL_MATRIX) { 8498 *newmat = mat; 8499 PetscCall(PetscObjectReference((PetscObject)mat)); 8500 } 8501 PetscFunctionReturn(PETSC_SUCCESS); 8502 } 8503 } 8504 8505 if (!iscol) { 8506 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8507 } else { 8508 iscoltmp = iscol; 8509 } 8510 8511 /* if original matrix is on just one processor then use submatrix generated */ 8512 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8513 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8514 goto setproperties; 8515 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8516 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8517 *newmat = *local; 8518 PetscCall(PetscFree(local)); 8519 goto setproperties; 8520 } else if (!mat->ops->createsubmatrix) { 8521 /* Create a new matrix type that implements the operation using the full matrix */ 8522 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8523 switch (cll) { 8524 case MAT_INITIAL_MATRIX: 8525 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8526 break; 8527 case MAT_REUSE_MATRIX: 8528 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8529 break; 8530 default: 8531 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8532 } 8533 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8534 goto setproperties; 8535 } 8536 8537 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8538 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8539 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8540 8541 setproperties: 8542 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8543 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8544 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8545 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8546 PetscFunctionReturn(PETSC_SUCCESS); 8547 } 8548 8549 /*@ 8550 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8551 8552 Not Collective 8553 8554 Input Parameters: 8555 + A - the matrix we wish to propagate options from 8556 - B - the matrix we wish to propagate options to 8557 8558 Level: beginner 8559 8560 Note: 8561 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8562 8563 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8564 @*/ 8565 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8566 { 8567 PetscFunctionBegin; 8568 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8569 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8570 B->symmetry_eternal = A->symmetry_eternal; 8571 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8572 B->symmetric = A->symmetric; 8573 B->structurally_symmetric = A->structurally_symmetric; 8574 B->spd = A->spd; 8575 B->hermitian = A->hermitian; 8576 PetscFunctionReturn(PETSC_SUCCESS); 8577 } 8578 8579 /*@ 8580 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8581 used during the assembly process to store values that belong to 8582 other processors. 8583 8584 Not Collective 8585 8586 Input Parameters: 8587 + mat - the matrix 8588 . size - the initial size of the stash. 8589 - bsize - the initial size of the block-stash(if used). 8590 8591 Options Database Keys: 8592 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8593 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8594 8595 Level: intermediate 8596 8597 Notes: 8598 The block-stash is used for values set with `MatSetValuesBlocked()` while 8599 the stash is used for values set with `MatSetValues()` 8600 8601 Run with the option -info and look for output of the form 8602 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8603 to determine the appropriate value, MM, to use for size and 8604 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8605 to determine the value, BMM to use for bsize 8606 8607 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8608 @*/ 8609 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8610 { 8611 PetscFunctionBegin; 8612 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8613 PetscValidType(mat, 1); 8614 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8615 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8616 PetscFunctionReturn(PETSC_SUCCESS); 8617 } 8618 8619 /*@ 8620 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8621 the matrix 8622 8623 Neighbor-wise Collective 8624 8625 Input Parameters: 8626 + A - the matrix 8627 . x - the vector to be multiplied by the interpolation operator 8628 - y - the vector to be added to the result 8629 8630 Output Parameter: 8631 . w - the resulting vector 8632 8633 Level: intermediate 8634 8635 Notes: 8636 `w` may be the same vector as `y`. 8637 8638 This allows one to use either the restriction or interpolation (its transpose) 8639 matrix to do the interpolation 8640 8641 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8642 @*/ 8643 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8644 { 8645 PetscInt M, N, Ny; 8646 8647 PetscFunctionBegin; 8648 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8649 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8650 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8651 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8652 PetscCall(MatGetSize(A, &M, &N)); 8653 PetscCall(VecGetSize(y, &Ny)); 8654 if (M == Ny) { 8655 PetscCall(MatMultAdd(A, x, y, w)); 8656 } else { 8657 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8658 } 8659 PetscFunctionReturn(PETSC_SUCCESS); 8660 } 8661 8662 /*@ 8663 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8664 the matrix 8665 8666 Neighbor-wise Collective 8667 8668 Input Parameters: 8669 + A - the matrix 8670 - x - the vector to be interpolated 8671 8672 Output Parameter: 8673 . y - the resulting vector 8674 8675 Level: intermediate 8676 8677 Note: 8678 This allows one to use either the restriction or interpolation (its transpose) 8679 matrix to do the interpolation 8680 8681 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8682 @*/ 8683 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8684 { 8685 PetscInt M, N, Ny; 8686 8687 PetscFunctionBegin; 8688 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8689 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8690 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8691 PetscCall(MatGetSize(A, &M, &N)); 8692 PetscCall(VecGetSize(y, &Ny)); 8693 if (M == Ny) { 8694 PetscCall(MatMult(A, x, y)); 8695 } else { 8696 PetscCall(MatMultTranspose(A, x, y)); 8697 } 8698 PetscFunctionReturn(PETSC_SUCCESS); 8699 } 8700 8701 /*@ 8702 MatRestrict - $y = A*x$ or $A^T*x$ 8703 8704 Neighbor-wise Collective 8705 8706 Input Parameters: 8707 + A - the matrix 8708 - x - the vector to be restricted 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 restriction 8718 8719 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8720 @*/ 8721 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8722 { 8723 PetscInt M, N, Nx; 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(x, &Nx)); 8731 if (M == Nx) { 8732 PetscCall(MatMultTranspose(A, x, y)); 8733 } else { 8734 PetscCall(MatMult(A, x, y)); 8735 } 8736 PetscFunctionReturn(PETSC_SUCCESS); 8737 } 8738 8739 /*@ 8740 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8741 8742 Neighbor-wise Collective 8743 8744 Input Parameters: 8745 + A - the matrix 8746 . x - the input dense matrix to be multiplied 8747 - w - the input dense matrix to be added to the result 8748 8749 Output Parameter: 8750 . y - the output dense matrix 8751 8752 Level: intermediate 8753 8754 Note: 8755 This allows one to use either the restriction or interpolation (its transpose) 8756 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8757 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8758 8759 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8760 @*/ 8761 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8762 { 8763 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8764 PetscBool trans = PETSC_TRUE; 8765 MatReuse reuse = MAT_INITIAL_MATRIX; 8766 8767 PetscFunctionBegin; 8768 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8769 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8770 PetscValidType(x, 2); 8771 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8772 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8773 PetscCall(MatGetSize(A, &M, &N)); 8774 PetscCall(MatGetSize(x, &Mx, &Nx)); 8775 if (N == Mx) trans = PETSC_FALSE; 8776 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); 8777 Mo = trans ? N : M; 8778 if (*y) { 8779 PetscCall(MatGetSize(*y, &My, &Ny)); 8780 if (Mo == My && Nx == Ny) { 8781 reuse = MAT_REUSE_MATRIX; 8782 } else { 8783 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); 8784 PetscCall(MatDestroy(y)); 8785 } 8786 } 8787 8788 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8789 PetscBool flg; 8790 8791 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8792 if (w) { 8793 PetscInt My, Ny, Mw, Nw; 8794 8795 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8796 PetscCall(MatGetSize(*y, &My, &Ny)); 8797 PetscCall(MatGetSize(w, &Mw, &Nw)); 8798 if (!flg || My != Mw || Ny != Nw) w = NULL; 8799 } 8800 if (!w) { 8801 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8802 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8803 PetscCall(PetscObjectDereference((PetscObject)w)); 8804 } else { 8805 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8806 } 8807 } 8808 if (!trans) { 8809 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8810 } else { 8811 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8812 } 8813 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8814 PetscFunctionReturn(PETSC_SUCCESS); 8815 } 8816 8817 /*@ 8818 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8819 8820 Neighbor-wise Collective 8821 8822 Input Parameters: 8823 + A - the matrix 8824 - x - the input dense matrix 8825 8826 Output Parameter: 8827 . y - the output dense matrix 8828 8829 Level: intermediate 8830 8831 Note: 8832 This allows one to use either the restriction or interpolation (its transpose) 8833 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8834 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8835 8836 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8837 @*/ 8838 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8839 { 8840 PetscFunctionBegin; 8841 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8842 PetscFunctionReturn(PETSC_SUCCESS); 8843 } 8844 8845 /*@ 8846 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8847 8848 Neighbor-wise Collective 8849 8850 Input Parameters: 8851 + A - the matrix 8852 - x - the input dense matrix 8853 8854 Output Parameter: 8855 . y - the output dense matrix 8856 8857 Level: intermediate 8858 8859 Note: 8860 This allows one to use either the restriction or interpolation (its transpose) 8861 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8862 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8863 8864 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8865 @*/ 8866 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8867 { 8868 PetscFunctionBegin; 8869 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8870 PetscFunctionReturn(PETSC_SUCCESS); 8871 } 8872 8873 /*@ 8874 MatGetNullSpace - retrieves the null space of a matrix. 8875 8876 Logically Collective 8877 8878 Input Parameters: 8879 + mat - the matrix 8880 - nullsp - the null space object 8881 8882 Level: developer 8883 8884 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8885 @*/ 8886 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8887 { 8888 PetscFunctionBegin; 8889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8890 PetscAssertPointer(nullsp, 2); 8891 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8892 PetscFunctionReturn(PETSC_SUCCESS); 8893 } 8894 8895 /*@C 8896 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8897 8898 Logically Collective 8899 8900 Input Parameters: 8901 + n - the number of matrices 8902 - mat - the array of matrices 8903 8904 Output Parameters: 8905 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space 8906 8907 Level: developer 8908 8909 Note: 8910 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8911 8912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8913 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8914 @*/ 8915 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8916 { 8917 PetscFunctionBegin; 8918 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8919 PetscAssertPointer(mat, 2); 8920 PetscAssertPointer(nullsp, 3); 8921 8922 PetscCall(PetscCalloc1(3 * n, nullsp)); 8923 for (PetscInt i = 0; i < n; i++) { 8924 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8925 (*nullsp)[i] = mat[i]->nullsp; 8926 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8927 (*nullsp)[n + i] = mat[i]->nearnullsp; 8928 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8929 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8930 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8931 } 8932 PetscFunctionReturn(PETSC_SUCCESS); 8933 } 8934 8935 /*@C 8936 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8937 8938 Logically Collective 8939 8940 Input Parameters: 8941 + n - the number of matrices 8942 . mat - the array of matrices 8943 - nullsp - an array of null spaces, `NULL` if the null space does not exist 8944 8945 Level: developer 8946 8947 Note: 8948 Call `MatGetNullSpaces()` to create `nullsp` 8949 8950 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8951 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8952 @*/ 8953 PetscErrorCode MatRestoreNullSpaces(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 PetscAssertPointer(*nullsp, 3); 8960 8961 for (PetscInt i = 0; i < n; i++) { 8962 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8963 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8964 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8965 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8966 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8967 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8968 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8969 } 8970 PetscCall(PetscFree(*nullsp)); 8971 PetscFunctionReturn(PETSC_SUCCESS); 8972 } 8973 8974 /*@ 8975 MatSetNullSpace - attaches a null space to a matrix. 8976 8977 Logically Collective 8978 8979 Input Parameters: 8980 + mat - the matrix 8981 - nullsp - the null space object 8982 8983 Level: advanced 8984 8985 Notes: 8986 This null space is used by the `KSP` linear solvers to solve singular systems. 8987 8988 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` 8989 8990 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 8991 to zero but the linear system will still be solved in a least squares sense. 8992 8993 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8994 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)$. 8995 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 8996 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 8997 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$). 8998 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8999 9000 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9001 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9002 routine also automatically calls `MatSetTransposeNullSpace()`. 9003 9004 The user should call `MatNullSpaceDestroy()`. 9005 9006 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9007 `KSPSetPCSide()` 9008 @*/ 9009 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9010 { 9011 PetscFunctionBegin; 9012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9013 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9014 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9015 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9016 mat->nullsp = nullsp; 9017 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9018 PetscFunctionReturn(PETSC_SUCCESS); 9019 } 9020 9021 /*@ 9022 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9023 9024 Logically Collective 9025 9026 Input Parameters: 9027 + mat - the matrix 9028 - nullsp - the null space object 9029 9030 Level: developer 9031 9032 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9033 @*/ 9034 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9035 { 9036 PetscFunctionBegin; 9037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9038 PetscValidType(mat, 1); 9039 PetscAssertPointer(nullsp, 2); 9040 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9041 PetscFunctionReturn(PETSC_SUCCESS); 9042 } 9043 9044 /*@ 9045 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9046 9047 Logically Collective 9048 9049 Input Parameters: 9050 + mat - the matrix 9051 - nullsp - the null space object 9052 9053 Level: advanced 9054 9055 Notes: 9056 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9057 9058 See `MatSetNullSpace()` 9059 9060 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9061 @*/ 9062 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9063 { 9064 PetscFunctionBegin; 9065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9066 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9067 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9068 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9069 mat->transnullsp = nullsp; 9070 PetscFunctionReturn(PETSC_SUCCESS); 9071 } 9072 9073 /*@ 9074 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9075 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9076 9077 Logically Collective 9078 9079 Input Parameters: 9080 + mat - the matrix 9081 - nullsp - the null space object 9082 9083 Level: advanced 9084 9085 Notes: 9086 Overwrites any previous near null space that may have been attached 9087 9088 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9089 9090 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9091 @*/ 9092 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9093 { 9094 PetscFunctionBegin; 9095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9096 PetscValidType(mat, 1); 9097 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9098 MatCheckPreallocated(mat, 1); 9099 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9100 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9101 mat->nearnullsp = nullsp; 9102 PetscFunctionReturn(PETSC_SUCCESS); 9103 } 9104 9105 /*@ 9106 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9107 9108 Not Collective 9109 9110 Input Parameter: 9111 . mat - the matrix 9112 9113 Output Parameter: 9114 . nullsp - the null space object, `NULL` if not set 9115 9116 Level: advanced 9117 9118 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9119 @*/ 9120 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9121 { 9122 PetscFunctionBegin; 9123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9124 PetscValidType(mat, 1); 9125 PetscAssertPointer(nullsp, 2); 9126 MatCheckPreallocated(mat, 1); 9127 *nullsp = mat->nearnullsp; 9128 PetscFunctionReturn(PETSC_SUCCESS); 9129 } 9130 9131 /*@C 9132 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9133 9134 Collective 9135 9136 Input Parameters: 9137 + mat - the matrix 9138 . row - row/column permutation 9139 - info - information on desired factorization process 9140 9141 Level: developer 9142 9143 Notes: 9144 Probably really in-place only when level of fill is zero, otherwise allocates 9145 new space to store factored matrix and deletes previous memory. 9146 9147 Most users should employ the `KSP` interface for linear solvers 9148 instead of working directly with matrix algebra routines such as this. 9149 See, e.g., `KSPCreate()`. 9150 9151 Developer Note: 9152 The Fortran interface is not autogenerated as the 9153 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9154 9155 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9156 @*/ 9157 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9158 { 9159 PetscFunctionBegin; 9160 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9161 PetscValidType(mat, 1); 9162 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9163 PetscAssertPointer(info, 3); 9164 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9165 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9166 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9167 MatCheckPreallocated(mat, 1); 9168 PetscUseTypeMethod(mat, iccfactor, row, info); 9169 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9170 PetscFunctionReturn(PETSC_SUCCESS); 9171 } 9172 9173 /*@ 9174 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9175 ghosted ones. 9176 9177 Not Collective 9178 9179 Input Parameters: 9180 + mat - the matrix 9181 - diag - the diagonal values, including ghost ones 9182 9183 Level: developer 9184 9185 Notes: 9186 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9187 9188 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9189 9190 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9191 @*/ 9192 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9193 { 9194 PetscMPIInt size; 9195 9196 PetscFunctionBegin; 9197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9198 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9199 PetscValidType(mat, 1); 9200 9201 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9202 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9203 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9204 if (size == 1) { 9205 PetscInt n, m; 9206 PetscCall(VecGetSize(diag, &n)); 9207 PetscCall(MatGetSize(mat, NULL, &m)); 9208 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9209 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9210 } else { 9211 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9212 } 9213 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9214 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9215 PetscFunctionReturn(PETSC_SUCCESS); 9216 } 9217 9218 /*@ 9219 MatGetInertia - Gets the inertia from a factored matrix 9220 9221 Collective 9222 9223 Input Parameter: 9224 . mat - the matrix 9225 9226 Output Parameters: 9227 + nneg - number of negative eigenvalues 9228 . nzero - number of zero eigenvalues 9229 - npos - number of positive eigenvalues 9230 9231 Level: advanced 9232 9233 Note: 9234 Matrix must have been factored by `MatCholeskyFactor()` 9235 9236 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9237 @*/ 9238 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9239 { 9240 PetscFunctionBegin; 9241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9242 PetscValidType(mat, 1); 9243 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9244 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9245 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9246 PetscFunctionReturn(PETSC_SUCCESS); 9247 } 9248 9249 /*@C 9250 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9251 9252 Neighbor-wise Collective 9253 9254 Input Parameters: 9255 + mat - the factored matrix obtained with `MatGetFactor()` 9256 - b - the right-hand-side vectors 9257 9258 Output Parameter: 9259 . x - the result vectors 9260 9261 Level: developer 9262 9263 Note: 9264 The vectors `b` and `x` cannot be the same. I.e., one cannot 9265 call `MatSolves`(A,x,x). 9266 9267 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9268 @*/ 9269 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9270 { 9271 PetscFunctionBegin; 9272 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9273 PetscValidType(mat, 1); 9274 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9275 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9276 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9277 9278 MatCheckPreallocated(mat, 1); 9279 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9280 PetscUseTypeMethod(mat, solves, b, x); 9281 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9282 PetscFunctionReturn(PETSC_SUCCESS); 9283 } 9284 9285 /*@ 9286 MatIsSymmetric - Test whether a matrix is symmetric 9287 9288 Collective 9289 9290 Input Parameters: 9291 + A - the matrix to test 9292 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9293 9294 Output Parameter: 9295 . flg - the result 9296 9297 Level: intermediate 9298 9299 Notes: 9300 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9301 9302 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9303 9304 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9305 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9306 9307 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9308 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9309 @*/ 9310 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9311 { 9312 PetscFunctionBegin; 9313 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9314 PetscAssertPointer(flg, 3); 9315 9316 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9317 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9318 else { 9319 PetscUseTypeMethod(A, issymmetric, tol, flg); 9320 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9321 } 9322 PetscFunctionReturn(PETSC_SUCCESS); 9323 } 9324 9325 /*@ 9326 MatIsHermitian - Test whether a matrix is Hermitian 9327 9328 Collective 9329 9330 Input Parameters: 9331 + A - the matrix to test 9332 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9333 9334 Output Parameter: 9335 . flg - the result 9336 9337 Level: intermediate 9338 9339 Notes: 9340 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9341 9342 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9343 9344 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9345 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9346 9347 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9348 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9349 @*/ 9350 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9351 { 9352 PetscFunctionBegin; 9353 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9354 PetscAssertPointer(flg, 3); 9355 9356 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9357 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9358 else { 9359 PetscUseTypeMethod(A, ishermitian, tol, flg); 9360 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9361 } 9362 PetscFunctionReturn(PETSC_SUCCESS); 9363 } 9364 9365 /*@ 9366 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9367 9368 Not Collective 9369 9370 Input Parameter: 9371 . A - the matrix to check 9372 9373 Output Parameters: 9374 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9375 - flg - the result (only valid if set is `PETSC_TRUE`) 9376 9377 Level: advanced 9378 9379 Notes: 9380 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9381 if you want it explicitly checked 9382 9383 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9384 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9385 9386 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9387 @*/ 9388 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9389 { 9390 PetscFunctionBegin; 9391 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9392 PetscAssertPointer(set, 2); 9393 PetscAssertPointer(flg, 3); 9394 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9395 *set = PETSC_TRUE; 9396 *flg = PetscBool3ToBool(A->symmetric); 9397 } else { 9398 *set = PETSC_FALSE; 9399 } 9400 PetscFunctionReturn(PETSC_SUCCESS); 9401 } 9402 9403 /*@ 9404 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9405 9406 Not Collective 9407 9408 Input Parameter: 9409 . A - the matrix to check 9410 9411 Output Parameters: 9412 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9413 - flg - the result (only valid if set is `PETSC_TRUE`) 9414 9415 Level: advanced 9416 9417 Notes: 9418 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9419 9420 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9421 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9422 9423 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9424 @*/ 9425 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9426 { 9427 PetscFunctionBegin; 9428 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9429 PetscAssertPointer(set, 2); 9430 PetscAssertPointer(flg, 3); 9431 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9432 *set = PETSC_TRUE; 9433 *flg = PetscBool3ToBool(A->spd); 9434 } else { 9435 *set = PETSC_FALSE; 9436 } 9437 PetscFunctionReturn(PETSC_SUCCESS); 9438 } 9439 9440 /*@ 9441 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9442 9443 Not Collective 9444 9445 Input Parameter: 9446 . A - the matrix to check 9447 9448 Output Parameters: 9449 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9450 - flg - the result (only valid if set is `PETSC_TRUE`) 9451 9452 Level: advanced 9453 9454 Notes: 9455 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9456 if you want it explicitly checked 9457 9458 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9459 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9460 9461 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9462 @*/ 9463 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9464 { 9465 PetscFunctionBegin; 9466 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9467 PetscAssertPointer(set, 2); 9468 PetscAssertPointer(flg, 3); 9469 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9470 *set = PETSC_TRUE; 9471 *flg = PetscBool3ToBool(A->hermitian); 9472 } else { 9473 *set = PETSC_FALSE; 9474 } 9475 PetscFunctionReturn(PETSC_SUCCESS); 9476 } 9477 9478 /*@ 9479 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9480 9481 Collective 9482 9483 Input Parameter: 9484 . A - the matrix to test 9485 9486 Output Parameter: 9487 . flg - the result 9488 9489 Level: intermediate 9490 9491 Notes: 9492 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9493 9494 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 9495 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9496 9497 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9498 @*/ 9499 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9500 { 9501 PetscFunctionBegin; 9502 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9503 PetscAssertPointer(flg, 2); 9504 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9505 *flg = PetscBool3ToBool(A->structurally_symmetric); 9506 } else { 9507 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9508 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9509 } 9510 PetscFunctionReturn(PETSC_SUCCESS); 9511 } 9512 9513 /*@ 9514 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9515 9516 Not Collective 9517 9518 Input Parameter: 9519 . A - the matrix to check 9520 9521 Output Parameters: 9522 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9523 - flg - the result (only valid if set is PETSC_TRUE) 9524 9525 Level: advanced 9526 9527 Notes: 9528 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 9529 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9530 9531 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9532 9533 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9534 @*/ 9535 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9536 { 9537 PetscFunctionBegin; 9538 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9539 PetscAssertPointer(set, 2); 9540 PetscAssertPointer(flg, 3); 9541 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9542 *set = PETSC_TRUE; 9543 *flg = PetscBool3ToBool(A->structurally_symmetric); 9544 } else { 9545 *set = PETSC_FALSE; 9546 } 9547 PetscFunctionReturn(PETSC_SUCCESS); 9548 } 9549 9550 /*@ 9551 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9552 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9553 9554 Not Collective 9555 9556 Input Parameter: 9557 . mat - the matrix 9558 9559 Output Parameters: 9560 + nstash - the size of the stash 9561 . reallocs - the number of additional mallocs incurred. 9562 . bnstash - the size of the block stash 9563 - breallocs - the number of additional mallocs incurred.in the block stash 9564 9565 Level: advanced 9566 9567 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9568 @*/ 9569 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9570 { 9571 PetscFunctionBegin; 9572 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9573 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9574 PetscFunctionReturn(PETSC_SUCCESS); 9575 } 9576 9577 /*@C 9578 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9579 parallel layout, `PetscLayout` for rows and columns 9580 9581 Collective 9582 9583 Input Parameter: 9584 . mat - the matrix 9585 9586 Output Parameters: 9587 + right - (optional) vector that the matrix can be multiplied against 9588 - left - (optional) vector that the matrix vector product can be stored in 9589 9590 Level: advanced 9591 9592 Notes: 9593 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()`. 9594 9595 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9596 9597 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9598 @*/ 9599 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9600 { 9601 PetscFunctionBegin; 9602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9603 PetscValidType(mat, 1); 9604 if (mat->ops->getvecs) { 9605 PetscUseTypeMethod(mat, getvecs, right, left); 9606 } else { 9607 if (right) { 9608 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9609 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9610 PetscCall(VecSetType(*right, mat->defaultvectype)); 9611 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9612 if (mat->boundtocpu && mat->bindingpropagates) { 9613 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9614 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9615 } 9616 #endif 9617 } 9618 if (left) { 9619 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9620 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9621 PetscCall(VecSetType(*left, mat->defaultvectype)); 9622 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9623 if (mat->boundtocpu && mat->bindingpropagates) { 9624 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9625 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9626 } 9627 #endif 9628 } 9629 } 9630 PetscFunctionReturn(PETSC_SUCCESS); 9631 } 9632 9633 /*@C 9634 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9635 with default values. 9636 9637 Not Collective 9638 9639 Input Parameter: 9640 . info - the `MatFactorInfo` data structure 9641 9642 Level: developer 9643 9644 Notes: 9645 The solvers are generally used through the `KSP` and `PC` objects, for example 9646 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9647 9648 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9649 9650 Developer Note: 9651 The Fortran interface is not autogenerated as the 9652 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9653 9654 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9655 @*/ 9656 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9657 { 9658 PetscFunctionBegin; 9659 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9660 PetscFunctionReturn(PETSC_SUCCESS); 9661 } 9662 9663 /*@ 9664 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9665 9666 Collective 9667 9668 Input Parameters: 9669 + mat - the factored matrix 9670 - is - the index set defining the Schur indices (0-based) 9671 9672 Level: advanced 9673 9674 Notes: 9675 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9676 9677 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9678 9679 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9680 9681 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9682 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9683 @*/ 9684 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9685 { 9686 PetscErrorCode (*f)(Mat, IS); 9687 9688 PetscFunctionBegin; 9689 PetscValidType(mat, 1); 9690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9691 PetscValidType(is, 2); 9692 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9693 PetscCheckSameComm(mat, 1, is, 2); 9694 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9695 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9696 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9697 PetscCall(MatDestroy(&mat->schur)); 9698 PetscCall((*f)(mat, is)); 9699 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9700 PetscFunctionReturn(PETSC_SUCCESS); 9701 } 9702 9703 /*@ 9704 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9705 9706 Logically Collective 9707 9708 Input Parameters: 9709 + F - the factored matrix obtained by calling `MatGetFactor()` 9710 . S - location where to return the Schur complement, can be `NULL` 9711 - status - the status of the Schur complement matrix, can be `NULL` 9712 9713 Level: advanced 9714 9715 Notes: 9716 You must call `MatFactorSetSchurIS()` before calling this routine. 9717 9718 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9719 9720 The routine provides a copy of the Schur matrix stored within the solver data structures. 9721 The caller must destroy the object when it is no longer needed. 9722 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9723 9724 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) 9725 9726 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9727 9728 Developer Note: 9729 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9730 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9731 9732 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9733 @*/ 9734 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9735 { 9736 PetscFunctionBegin; 9737 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9738 if (S) PetscAssertPointer(S, 2); 9739 if (status) PetscAssertPointer(status, 3); 9740 if (S) { 9741 PetscErrorCode (*f)(Mat, Mat *); 9742 9743 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9744 if (f) { 9745 PetscCall((*f)(F, S)); 9746 } else { 9747 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9748 } 9749 } 9750 if (status) *status = F->schur_status; 9751 PetscFunctionReturn(PETSC_SUCCESS); 9752 } 9753 9754 /*@ 9755 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9756 9757 Logically Collective 9758 9759 Input Parameters: 9760 + F - the factored matrix obtained by calling `MatGetFactor()` 9761 . S - location where to return the Schur complement, can be `NULL` 9762 - status - the status of the Schur complement matrix, can be `NULL` 9763 9764 Level: advanced 9765 9766 Notes: 9767 You must call `MatFactorSetSchurIS()` before calling this routine. 9768 9769 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9770 9771 The routine returns a the Schur Complement stored within the data structures of the solver. 9772 9773 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9774 9775 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9776 9777 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9778 9779 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9780 9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9782 @*/ 9783 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9784 { 9785 PetscFunctionBegin; 9786 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9787 if (S) { 9788 PetscAssertPointer(S, 2); 9789 *S = F->schur; 9790 } 9791 if (status) { 9792 PetscAssertPointer(status, 3); 9793 *status = F->schur_status; 9794 } 9795 PetscFunctionReturn(PETSC_SUCCESS); 9796 } 9797 9798 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9799 { 9800 Mat S = F->schur; 9801 9802 PetscFunctionBegin; 9803 switch (F->schur_status) { 9804 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9805 case MAT_FACTOR_SCHUR_INVERTED: 9806 if (S) { 9807 S->ops->solve = NULL; 9808 S->ops->matsolve = NULL; 9809 S->ops->solvetranspose = NULL; 9810 S->ops->matsolvetranspose = NULL; 9811 S->ops->solveadd = NULL; 9812 S->ops->solvetransposeadd = NULL; 9813 S->factortype = MAT_FACTOR_NONE; 9814 PetscCall(PetscFree(S->solvertype)); 9815 } 9816 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9817 break; 9818 default: 9819 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9820 } 9821 PetscFunctionReturn(PETSC_SUCCESS); 9822 } 9823 9824 /*@ 9825 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9826 9827 Logically Collective 9828 9829 Input Parameters: 9830 + F - the factored matrix obtained by calling `MatGetFactor()` 9831 . S - location where the Schur complement is stored 9832 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9833 9834 Level: advanced 9835 9836 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9837 @*/ 9838 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9839 { 9840 PetscFunctionBegin; 9841 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9842 if (S) { 9843 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9844 *S = NULL; 9845 } 9846 F->schur_status = status; 9847 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9848 PetscFunctionReturn(PETSC_SUCCESS); 9849 } 9850 9851 /*@ 9852 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9853 9854 Logically Collective 9855 9856 Input Parameters: 9857 + F - the factored matrix obtained by calling `MatGetFactor()` 9858 . rhs - location where the right hand side of the Schur complement system is stored 9859 - sol - location where the solution of the Schur complement system has to be returned 9860 9861 Level: advanced 9862 9863 Notes: 9864 The sizes of the vectors should match the size of the Schur complement 9865 9866 Must be called after `MatFactorSetSchurIS()` 9867 9868 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9869 @*/ 9870 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9871 { 9872 PetscFunctionBegin; 9873 PetscValidType(F, 1); 9874 PetscValidType(rhs, 2); 9875 PetscValidType(sol, 3); 9876 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9877 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9878 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9879 PetscCheckSameComm(F, 1, rhs, 2); 9880 PetscCheckSameComm(F, 1, sol, 3); 9881 PetscCall(MatFactorFactorizeSchurComplement(F)); 9882 switch (F->schur_status) { 9883 case MAT_FACTOR_SCHUR_FACTORED: 9884 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9885 break; 9886 case MAT_FACTOR_SCHUR_INVERTED: 9887 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9888 break; 9889 default: 9890 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9891 } 9892 PetscFunctionReturn(PETSC_SUCCESS); 9893 } 9894 9895 /*@ 9896 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9897 9898 Logically Collective 9899 9900 Input Parameters: 9901 + F - the factored matrix obtained by calling `MatGetFactor()` 9902 . rhs - location where the right hand side of the Schur complement system is stored 9903 - sol - location where the solution of the Schur complement system has to be returned 9904 9905 Level: advanced 9906 9907 Notes: 9908 The sizes of the vectors should match the size of the Schur complement 9909 9910 Must be called after `MatFactorSetSchurIS()` 9911 9912 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9913 @*/ 9914 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9915 { 9916 PetscFunctionBegin; 9917 PetscValidType(F, 1); 9918 PetscValidType(rhs, 2); 9919 PetscValidType(sol, 3); 9920 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9921 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9922 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9923 PetscCheckSameComm(F, 1, rhs, 2); 9924 PetscCheckSameComm(F, 1, sol, 3); 9925 PetscCall(MatFactorFactorizeSchurComplement(F)); 9926 switch (F->schur_status) { 9927 case MAT_FACTOR_SCHUR_FACTORED: 9928 PetscCall(MatSolve(F->schur, rhs, sol)); 9929 break; 9930 case MAT_FACTOR_SCHUR_INVERTED: 9931 PetscCall(MatMult(F->schur, rhs, sol)); 9932 break; 9933 default: 9934 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9935 } 9936 PetscFunctionReturn(PETSC_SUCCESS); 9937 } 9938 9939 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9940 #if PetscDefined(HAVE_CUDA) 9941 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9942 #endif 9943 9944 /* Schur status updated in the interface */ 9945 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9946 { 9947 Mat S = F->schur; 9948 9949 PetscFunctionBegin; 9950 if (S) { 9951 PetscMPIInt size; 9952 PetscBool isdense, isdensecuda; 9953 9954 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9955 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9956 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9957 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9958 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9959 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9960 if (isdense) { 9961 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9962 } else if (isdensecuda) { 9963 #if defined(PETSC_HAVE_CUDA) 9964 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9965 #endif 9966 } 9967 // HIP?????????????? 9968 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9969 } 9970 PetscFunctionReturn(PETSC_SUCCESS); 9971 } 9972 9973 /*@ 9974 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9975 9976 Logically Collective 9977 9978 Input Parameter: 9979 . F - the factored matrix obtained by calling `MatGetFactor()` 9980 9981 Level: advanced 9982 9983 Notes: 9984 Must be called after `MatFactorSetSchurIS()`. 9985 9986 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9987 9988 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9989 @*/ 9990 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9991 { 9992 PetscFunctionBegin; 9993 PetscValidType(F, 1); 9994 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9995 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9996 PetscCall(MatFactorFactorizeSchurComplement(F)); 9997 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9998 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9999 PetscFunctionReturn(PETSC_SUCCESS); 10000 } 10001 10002 /*@ 10003 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10004 10005 Logically Collective 10006 10007 Input Parameter: 10008 . F - the factored matrix obtained by calling `MatGetFactor()` 10009 10010 Level: advanced 10011 10012 Note: 10013 Must be called after `MatFactorSetSchurIS()` 10014 10015 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10016 @*/ 10017 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10018 { 10019 MatFactorInfo info; 10020 10021 PetscFunctionBegin; 10022 PetscValidType(F, 1); 10023 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10024 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10025 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10026 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10027 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10028 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10029 } else { 10030 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10031 } 10032 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10033 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10034 PetscFunctionReturn(PETSC_SUCCESS); 10035 } 10036 10037 /*@ 10038 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10039 10040 Neighbor-wise Collective 10041 10042 Input Parameters: 10043 + A - the matrix 10044 . P - the projection matrix 10045 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10046 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10047 if the result is a dense matrix this is irrelevant 10048 10049 Output Parameter: 10050 . C - the product matrix 10051 10052 Level: intermediate 10053 10054 Notes: 10055 C will be created and must be destroyed by the user with `MatDestroy()`. 10056 10057 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10058 10059 Developer Note: 10060 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10061 10062 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10063 @*/ 10064 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10065 { 10066 PetscFunctionBegin; 10067 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10068 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10069 10070 if (scall == MAT_INITIAL_MATRIX) { 10071 PetscCall(MatProductCreate(A, P, NULL, C)); 10072 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10073 PetscCall(MatProductSetAlgorithm(*C, "default")); 10074 PetscCall(MatProductSetFill(*C, fill)); 10075 10076 (*C)->product->api_user = PETSC_TRUE; 10077 PetscCall(MatProductSetFromOptions(*C)); 10078 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); 10079 PetscCall(MatProductSymbolic(*C)); 10080 } else { /* scall == MAT_REUSE_MATRIX */ 10081 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10082 } 10083 10084 PetscCall(MatProductNumeric(*C)); 10085 (*C)->symmetric = A->symmetric; 10086 (*C)->spd = A->spd; 10087 PetscFunctionReturn(PETSC_SUCCESS); 10088 } 10089 10090 /*@ 10091 MatRARt - Creates the matrix product $C = R * A * R^T$ 10092 10093 Neighbor-wise Collective 10094 10095 Input Parameters: 10096 + A - the matrix 10097 . R - the projection matrix 10098 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10099 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10100 if the result is a dense matrix this is irrelevant 10101 10102 Output Parameter: 10103 . C - the product matrix 10104 10105 Level: intermediate 10106 10107 Notes: 10108 C will be created and must be destroyed by the user with `MatDestroy()`. 10109 10110 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10111 10112 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10113 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10114 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10115 We recommend using MatPtAP(). 10116 10117 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10118 @*/ 10119 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10120 { 10121 PetscFunctionBegin; 10122 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10123 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10124 10125 if (scall == MAT_INITIAL_MATRIX) { 10126 PetscCall(MatProductCreate(A, R, NULL, C)); 10127 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10128 PetscCall(MatProductSetAlgorithm(*C, "default")); 10129 PetscCall(MatProductSetFill(*C, fill)); 10130 10131 (*C)->product->api_user = PETSC_TRUE; 10132 PetscCall(MatProductSetFromOptions(*C)); 10133 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); 10134 PetscCall(MatProductSymbolic(*C)); 10135 } else { /* scall == MAT_REUSE_MATRIX */ 10136 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10137 } 10138 10139 PetscCall(MatProductNumeric(*C)); 10140 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10141 PetscFunctionReturn(PETSC_SUCCESS); 10142 } 10143 10144 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10145 { 10146 PetscBool flg = PETSC_TRUE; 10147 10148 PetscFunctionBegin; 10149 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10150 if (scall == MAT_INITIAL_MATRIX) { 10151 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10152 PetscCall(MatProductCreate(A, B, NULL, C)); 10153 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10154 PetscCall(MatProductSetFill(*C, fill)); 10155 } else { /* scall == MAT_REUSE_MATRIX */ 10156 Mat_Product *product = (*C)->product; 10157 10158 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10159 if (flg && product && product->type != ptype) { 10160 PetscCall(MatProductClear(*C)); 10161 product = NULL; 10162 } 10163 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10164 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10165 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10166 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10167 product = (*C)->product; 10168 product->fill = fill; 10169 product->clear = PETSC_TRUE; 10170 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10171 flg = PETSC_FALSE; 10172 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10173 } 10174 } 10175 if (flg) { 10176 (*C)->product->api_user = PETSC_TRUE; 10177 PetscCall(MatProductSetType(*C, ptype)); 10178 PetscCall(MatProductSetFromOptions(*C)); 10179 PetscCall(MatProductSymbolic(*C)); 10180 } 10181 PetscCall(MatProductNumeric(*C)); 10182 PetscFunctionReturn(PETSC_SUCCESS); 10183 } 10184 10185 /*@ 10186 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10187 10188 Neighbor-wise Collective 10189 10190 Input Parameters: 10191 + A - the left matrix 10192 . B - the right matrix 10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10194 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10195 if the result is a dense matrix this is irrelevant 10196 10197 Output Parameter: 10198 . C - the product matrix 10199 10200 Notes: 10201 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10202 10203 `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 10204 call to this function with `MAT_INITIAL_MATRIX`. 10205 10206 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10207 10208 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`, 10209 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10210 10211 Example of Usage: 10212 .vb 10213 MatProductCreate(A,B,NULL,&C); 10214 MatProductSetType(C,MATPRODUCT_AB); 10215 MatProductSymbolic(C); 10216 MatProductNumeric(C); // compute C=A * B 10217 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10218 MatProductNumeric(C); 10219 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10220 MatProductNumeric(C); 10221 .ve 10222 10223 Level: intermediate 10224 10225 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10226 @*/ 10227 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10228 { 10229 PetscFunctionBegin; 10230 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10231 PetscFunctionReturn(PETSC_SUCCESS); 10232 } 10233 10234 /*@ 10235 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10236 10237 Neighbor-wise Collective 10238 10239 Input Parameters: 10240 + A - the left matrix 10241 . B - the right matrix 10242 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10243 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10244 10245 Output Parameter: 10246 . C - the product matrix 10247 10248 Options Database Key: 10249 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10250 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10251 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10252 10253 Level: intermediate 10254 10255 Notes: 10256 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10257 10258 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10259 10260 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10261 actually needed. 10262 10263 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10264 and for pairs of `MATMPIDENSE` matrices. 10265 10266 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10267 10268 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10269 @*/ 10270 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10271 { 10272 PetscFunctionBegin; 10273 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10274 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10275 PetscFunctionReturn(PETSC_SUCCESS); 10276 } 10277 10278 /*@ 10279 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10280 10281 Neighbor-wise Collective 10282 10283 Input Parameters: 10284 + A - the left matrix 10285 . B - the right matrix 10286 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10287 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10288 10289 Output Parameter: 10290 . C - the product matrix 10291 10292 Level: intermediate 10293 10294 Notes: 10295 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10296 10297 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10298 10299 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10300 10301 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10302 actually needed. 10303 10304 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10305 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10306 10307 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10308 @*/ 10309 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10310 { 10311 PetscFunctionBegin; 10312 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10313 PetscFunctionReturn(PETSC_SUCCESS); 10314 } 10315 10316 /*@ 10317 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10318 10319 Neighbor-wise Collective 10320 10321 Input Parameters: 10322 + A - the left matrix 10323 . B - the middle matrix 10324 . C - the right matrix 10325 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10326 - 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 10327 if the result is a dense matrix this is irrelevant 10328 10329 Output Parameter: 10330 . D - the product matrix 10331 10332 Level: intermediate 10333 10334 Notes: 10335 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10336 10337 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10338 10339 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10340 10341 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10342 actually needed. 10343 10344 If you have many matrices with the same non-zero structure to multiply, you 10345 should use `MAT_REUSE_MATRIX` in all calls but the first 10346 10347 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10348 @*/ 10349 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10350 { 10351 PetscFunctionBegin; 10352 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10353 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10354 10355 if (scall == MAT_INITIAL_MATRIX) { 10356 PetscCall(MatProductCreate(A, B, C, D)); 10357 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10358 PetscCall(MatProductSetAlgorithm(*D, "default")); 10359 PetscCall(MatProductSetFill(*D, fill)); 10360 10361 (*D)->product->api_user = PETSC_TRUE; 10362 PetscCall(MatProductSetFromOptions(*D)); 10363 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, 10364 ((PetscObject)C)->type_name); 10365 PetscCall(MatProductSymbolic(*D)); 10366 } else { /* user may change input matrices when REUSE */ 10367 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10368 } 10369 PetscCall(MatProductNumeric(*D)); 10370 PetscFunctionReturn(PETSC_SUCCESS); 10371 } 10372 10373 /*@ 10374 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10375 10376 Collective 10377 10378 Input Parameters: 10379 + mat - the matrix 10380 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10381 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10382 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10383 10384 Output Parameter: 10385 . matredundant - redundant matrix 10386 10387 Level: advanced 10388 10389 Notes: 10390 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10391 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10392 10393 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10394 calling it. 10395 10396 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10397 10398 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10399 @*/ 10400 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10401 { 10402 MPI_Comm comm; 10403 PetscMPIInt size; 10404 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10405 Mat_Redundant *redund = NULL; 10406 PetscSubcomm psubcomm = NULL; 10407 MPI_Comm subcomm_in = subcomm; 10408 Mat *matseq; 10409 IS isrow, iscol; 10410 PetscBool newsubcomm = PETSC_FALSE; 10411 10412 PetscFunctionBegin; 10413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10414 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10415 PetscAssertPointer(*matredundant, 5); 10416 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10417 } 10418 10419 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10420 if (size == 1 || nsubcomm == 1) { 10421 if (reuse == MAT_INITIAL_MATRIX) { 10422 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10423 } else { 10424 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"); 10425 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10426 } 10427 PetscFunctionReturn(PETSC_SUCCESS); 10428 } 10429 10430 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10431 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10432 MatCheckPreallocated(mat, 1); 10433 10434 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10435 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10436 /* create psubcomm, then get subcomm */ 10437 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10438 PetscCallMPI(MPI_Comm_size(comm, &size)); 10439 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10440 10441 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10442 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10443 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10444 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10445 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10446 newsubcomm = PETSC_TRUE; 10447 PetscCall(PetscSubcommDestroy(&psubcomm)); 10448 } 10449 10450 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10451 if (reuse == MAT_INITIAL_MATRIX) { 10452 mloc_sub = PETSC_DECIDE; 10453 nloc_sub = PETSC_DECIDE; 10454 if (bs < 1) { 10455 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10456 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10457 } else { 10458 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10459 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10460 } 10461 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10462 rstart = rend - mloc_sub; 10463 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10464 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10465 PetscCall(ISSetIdentity(iscol)); 10466 } else { /* reuse == MAT_REUSE_MATRIX */ 10467 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"); 10468 /* retrieve subcomm */ 10469 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10470 redund = (*matredundant)->redundant; 10471 isrow = redund->isrow; 10472 iscol = redund->iscol; 10473 matseq = redund->matseq; 10474 } 10475 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10476 10477 /* get matredundant over subcomm */ 10478 if (reuse == MAT_INITIAL_MATRIX) { 10479 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10480 10481 /* create a supporting struct and attach it to C for reuse */ 10482 PetscCall(PetscNew(&redund)); 10483 (*matredundant)->redundant = redund; 10484 redund->isrow = isrow; 10485 redund->iscol = iscol; 10486 redund->matseq = matseq; 10487 if (newsubcomm) { 10488 redund->subcomm = subcomm; 10489 } else { 10490 redund->subcomm = MPI_COMM_NULL; 10491 } 10492 } else { 10493 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10494 } 10495 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10496 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10497 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10498 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10499 } 10500 #endif 10501 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10502 PetscFunctionReturn(PETSC_SUCCESS); 10503 } 10504 10505 /*@C 10506 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10507 a given `Mat`. Each submatrix can span multiple procs. 10508 10509 Collective 10510 10511 Input Parameters: 10512 + mat - the matrix 10513 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10514 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10515 10516 Output Parameter: 10517 . subMat - parallel sub-matrices each spanning a given `subcomm` 10518 10519 Level: advanced 10520 10521 Notes: 10522 The submatrix partition across processors is dictated by `subComm` a 10523 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10524 is not restricted to be grouped with consecutive original MPI processes. 10525 10526 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10527 map directly to the layout of the original matrix [wrt the local 10528 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10529 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10530 the `subMat`. However the offDiagMat looses some columns - and this is 10531 reconstructed with `MatSetValues()` 10532 10533 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10534 10535 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10536 @*/ 10537 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10538 { 10539 PetscMPIInt commsize, subCommSize; 10540 10541 PetscFunctionBegin; 10542 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10543 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10544 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10545 10546 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"); 10547 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10548 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10549 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10550 PetscFunctionReturn(PETSC_SUCCESS); 10551 } 10552 10553 /*@ 10554 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10555 10556 Not Collective 10557 10558 Input Parameters: 10559 + mat - matrix to extract local submatrix from 10560 . isrow - local row indices for submatrix 10561 - iscol - local column indices for submatrix 10562 10563 Output Parameter: 10564 . submat - the submatrix 10565 10566 Level: intermediate 10567 10568 Notes: 10569 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10570 10571 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10572 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10573 10574 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10575 `MatSetValuesBlockedLocal()` will also be implemented. 10576 10577 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10578 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10579 10580 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10581 @*/ 10582 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10583 { 10584 PetscFunctionBegin; 10585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10586 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10587 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10588 PetscCheckSameComm(isrow, 2, iscol, 3); 10589 PetscAssertPointer(submat, 4); 10590 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10591 10592 if (mat->ops->getlocalsubmatrix) { 10593 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10594 } else { 10595 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10596 } 10597 PetscFunctionReturn(PETSC_SUCCESS); 10598 } 10599 10600 /*@ 10601 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10602 10603 Not Collective 10604 10605 Input Parameters: 10606 + mat - matrix to extract local submatrix from 10607 . isrow - local row indices for submatrix 10608 . iscol - local column indices for submatrix 10609 - submat - the submatrix 10610 10611 Level: intermediate 10612 10613 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10614 @*/ 10615 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10616 { 10617 PetscFunctionBegin; 10618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10619 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10620 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10621 PetscCheckSameComm(isrow, 2, iscol, 3); 10622 PetscAssertPointer(submat, 4); 10623 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10624 10625 if (mat->ops->restorelocalsubmatrix) { 10626 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10627 } else { 10628 PetscCall(MatDestroy(submat)); 10629 } 10630 *submat = NULL; 10631 PetscFunctionReturn(PETSC_SUCCESS); 10632 } 10633 10634 /*@ 10635 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10636 10637 Collective 10638 10639 Input Parameter: 10640 . mat - the matrix 10641 10642 Output Parameter: 10643 . is - if any rows have zero diagonals this contains the list of them 10644 10645 Level: developer 10646 10647 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10648 @*/ 10649 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10650 { 10651 PetscFunctionBegin; 10652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10653 PetscValidType(mat, 1); 10654 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10655 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10656 10657 if (!mat->ops->findzerodiagonals) { 10658 Vec diag; 10659 const PetscScalar *a; 10660 PetscInt *rows; 10661 PetscInt rStart, rEnd, r, nrow = 0; 10662 10663 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10664 PetscCall(MatGetDiagonal(mat, diag)); 10665 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10666 PetscCall(VecGetArrayRead(diag, &a)); 10667 for (r = 0; r < rEnd - rStart; ++r) 10668 if (a[r] == 0.0) ++nrow; 10669 PetscCall(PetscMalloc1(nrow, &rows)); 10670 nrow = 0; 10671 for (r = 0; r < rEnd - rStart; ++r) 10672 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10673 PetscCall(VecRestoreArrayRead(diag, &a)); 10674 PetscCall(VecDestroy(&diag)); 10675 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10676 } else { 10677 PetscUseTypeMethod(mat, findzerodiagonals, is); 10678 } 10679 PetscFunctionReturn(PETSC_SUCCESS); 10680 } 10681 10682 /*@ 10683 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10684 10685 Collective 10686 10687 Input Parameter: 10688 . mat - the matrix 10689 10690 Output Parameter: 10691 . is - contains the list of rows with off block diagonal entries 10692 10693 Level: developer 10694 10695 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10696 @*/ 10697 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10698 { 10699 PetscFunctionBegin; 10700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10701 PetscValidType(mat, 1); 10702 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10703 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10704 10705 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10706 PetscFunctionReturn(PETSC_SUCCESS); 10707 } 10708 10709 /*@C 10710 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10711 10712 Collective; No Fortran Support 10713 10714 Input Parameter: 10715 . mat - the matrix 10716 10717 Output Parameter: 10718 . values - the block inverses in column major order (FORTRAN-like) 10719 10720 Level: advanced 10721 10722 Notes: 10723 The size of the blocks is determined by the block size of the matrix. 10724 10725 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10726 10727 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10728 10729 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10730 @*/ 10731 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10732 { 10733 PetscFunctionBegin; 10734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10735 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10736 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10737 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10738 PetscFunctionReturn(PETSC_SUCCESS); 10739 } 10740 10741 /*@C 10742 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10743 10744 Collective; No Fortran Support 10745 10746 Input Parameters: 10747 + mat - the matrix 10748 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10749 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10750 10751 Output Parameter: 10752 . values - the block inverses in column major order (FORTRAN-like) 10753 10754 Level: advanced 10755 10756 Notes: 10757 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10758 10759 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10760 10761 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10762 @*/ 10763 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10764 { 10765 PetscFunctionBegin; 10766 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10767 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10768 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10769 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10770 PetscFunctionReturn(PETSC_SUCCESS); 10771 } 10772 10773 /*@ 10774 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10775 10776 Collective 10777 10778 Input Parameters: 10779 + A - the matrix 10780 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10781 10782 Level: advanced 10783 10784 Note: 10785 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10786 10787 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10788 @*/ 10789 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10790 { 10791 const PetscScalar *vals; 10792 PetscInt *dnnz; 10793 PetscInt m, rstart, rend, bs, i, j; 10794 10795 PetscFunctionBegin; 10796 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10797 PetscCall(MatGetBlockSize(A, &bs)); 10798 PetscCall(MatGetLocalSize(A, &m, NULL)); 10799 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10800 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10801 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10802 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10803 PetscCall(PetscFree(dnnz)); 10804 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10805 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10806 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10807 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10808 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10809 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10810 PetscFunctionReturn(PETSC_SUCCESS); 10811 } 10812 10813 /*@C 10814 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10815 via `MatTransposeColoringCreate()`. 10816 10817 Collective 10818 10819 Input Parameter: 10820 . c - coloring context 10821 10822 Level: intermediate 10823 10824 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10825 @*/ 10826 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10827 { 10828 MatTransposeColoring matcolor = *c; 10829 10830 PetscFunctionBegin; 10831 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10832 if (--((PetscObject)matcolor)->refct > 0) { 10833 matcolor = NULL; 10834 PetscFunctionReturn(PETSC_SUCCESS); 10835 } 10836 10837 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10838 PetscCall(PetscFree(matcolor->rows)); 10839 PetscCall(PetscFree(matcolor->den2sp)); 10840 PetscCall(PetscFree(matcolor->colorforcol)); 10841 PetscCall(PetscFree(matcolor->columns)); 10842 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10843 PetscCall(PetscHeaderDestroy(c)); 10844 PetscFunctionReturn(PETSC_SUCCESS); 10845 } 10846 10847 /*@C 10848 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10849 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10850 `MatTransposeColoring` to sparse `B`. 10851 10852 Collective 10853 10854 Input Parameters: 10855 + coloring - coloring context created with `MatTransposeColoringCreate()` 10856 - B - sparse matrix 10857 10858 Output Parameter: 10859 . Btdense - dense matrix $B^T$ 10860 10861 Level: developer 10862 10863 Note: 10864 These are used internally for some implementations of `MatRARt()` 10865 10866 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10867 @*/ 10868 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10869 { 10870 PetscFunctionBegin; 10871 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10872 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10873 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10874 10875 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10876 PetscFunctionReturn(PETSC_SUCCESS); 10877 } 10878 10879 /*@C 10880 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10881 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10882 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10883 $C_{sp}$ from $C_{den}$. 10884 10885 Collective 10886 10887 Input Parameters: 10888 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10889 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10890 10891 Output Parameter: 10892 . Csp - sparse matrix 10893 10894 Level: developer 10895 10896 Note: 10897 These are used internally for some implementations of `MatRARt()` 10898 10899 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10900 @*/ 10901 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10902 { 10903 PetscFunctionBegin; 10904 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10905 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10906 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10907 10908 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10909 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10910 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10911 PetscFunctionReturn(PETSC_SUCCESS); 10912 } 10913 10914 /*@C 10915 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10916 10917 Collective 10918 10919 Input Parameters: 10920 + mat - the matrix product C 10921 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10922 10923 Output Parameter: 10924 . color - the new coloring context 10925 10926 Level: intermediate 10927 10928 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10929 `MatTransColoringApplyDenToSp()` 10930 @*/ 10931 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10932 { 10933 MatTransposeColoring c; 10934 MPI_Comm comm; 10935 10936 PetscFunctionBegin; 10937 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10938 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10939 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10940 10941 c->ctype = iscoloring->ctype; 10942 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10943 10944 *color = c; 10945 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10946 PetscFunctionReturn(PETSC_SUCCESS); 10947 } 10948 10949 /*@ 10950 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10951 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10952 same, otherwise it will be larger 10953 10954 Not Collective 10955 10956 Input Parameter: 10957 . mat - the matrix 10958 10959 Output Parameter: 10960 . state - the current state 10961 10962 Level: intermediate 10963 10964 Notes: 10965 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10966 different matrices 10967 10968 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10969 10970 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10971 10972 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10973 @*/ 10974 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10975 { 10976 PetscFunctionBegin; 10977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10978 *state = mat->nonzerostate; 10979 PetscFunctionReturn(PETSC_SUCCESS); 10980 } 10981 10982 /*@ 10983 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10984 matrices from each processor 10985 10986 Collective 10987 10988 Input Parameters: 10989 + comm - the communicators the parallel matrix will live on 10990 . seqmat - the input sequential matrices 10991 . n - number of local columns (or `PETSC_DECIDE`) 10992 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10993 10994 Output Parameter: 10995 . mpimat - the parallel matrix generated 10996 10997 Level: developer 10998 10999 Note: 11000 The number of columns of the matrix in EACH processor MUST be the same. 11001 11002 .seealso: [](ch_matrices), `Mat` 11003 @*/ 11004 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11005 { 11006 PetscMPIInt size; 11007 11008 PetscFunctionBegin; 11009 PetscCallMPI(MPI_Comm_size(comm, &size)); 11010 if (size == 1) { 11011 if (reuse == MAT_INITIAL_MATRIX) { 11012 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11013 } else { 11014 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11015 } 11016 PetscFunctionReturn(PETSC_SUCCESS); 11017 } 11018 11019 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"); 11020 11021 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11022 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11023 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11024 PetscFunctionReturn(PETSC_SUCCESS); 11025 } 11026 11027 /*@ 11028 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11029 11030 Collective 11031 11032 Input Parameters: 11033 + A - the matrix to create subdomains from 11034 - N - requested number of subdomains 11035 11036 Output Parameters: 11037 + n - number of subdomains resulting on this MPI process 11038 - iss - `IS` list with indices of subdomains on this MPI process 11039 11040 Level: advanced 11041 11042 Note: 11043 The number of subdomains must be smaller than the communicator size 11044 11045 .seealso: [](ch_matrices), `Mat`, `IS` 11046 @*/ 11047 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11048 { 11049 MPI_Comm comm, subcomm; 11050 PetscMPIInt size, rank, color; 11051 PetscInt rstart, rend, k; 11052 11053 PetscFunctionBegin; 11054 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11055 PetscCallMPI(MPI_Comm_size(comm, &size)); 11056 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11057 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); 11058 *n = 1; 11059 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11060 color = rank / k; 11061 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11062 PetscCall(PetscMalloc1(1, iss)); 11063 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11064 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11065 PetscCallMPI(MPI_Comm_free(&subcomm)); 11066 PetscFunctionReturn(PETSC_SUCCESS); 11067 } 11068 11069 /*@ 11070 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11071 11072 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11073 If they are not the same, uses `MatMatMatMult()`. 11074 11075 Once the coarse grid problem is constructed, correct for interpolation operators 11076 that are not of full rank, which can legitimately happen in the case of non-nested 11077 geometric multigrid. 11078 11079 Input Parameters: 11080 + restrct - restriction operator 11081 . dA - fine grid matrix 11082 . interpolate - interpolation operator 11083 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11084 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11085 11086 Output Parameter: 11087 . A - the Galerkin coarse matrix 11088 11089 Options Database Key: 11090 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11091 11092 Level: developer 11093 11094 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11095 @*/ 11096 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11097 { 11098 IS zerorows; 11099 Vec diag; 11100 11101 PetscFunctionBegin; 11102 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11103 /* Construct the coarse grid matrix */ 11104 if (interpolate == restrct) { 11105 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11106 } else { 11107 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11108 } 11109 11110 /* If the interpolation matrix is not of full rank, A will have zero rows. 11111 This can legitimately happen in the case of non-nested geometric multigrid. 11112 In that event, we set the rows of the matrix to the rows of the identity, 11113 ignoring the equations (as the RHS will also be zero). */ 11114 11115 PetscCall(MatFindZeroRows(*A, &zerorows)); 11116 11117 if (zerorows != NULL) { /* if there are any zero rows */ 11118 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11119 PetscCall(MatGetDiagonal(*A, diag)); 11120 PetscCall(VecISSet(diag, zerorows, 1.0)); 11121 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11122 PetscCall(VecDestroy(&diag)); 11123 PetscCall(ISDestroy(&zerorows)); 11124 } 11125 PetscFunctionReturn(PETSC_SUCCESS); 11126 } 11127 11128 /*@C 11129 MatSetOperation - Allows user to set a matrix operation for any matrix type 11130 11131 Logically Collective 11132 11133 Input Parameters: 11134 + mat - the matrix 11135 . op - the name of the operation 11136 - f - the function that provides the operation 11137 11138 Level: developer 11139 11140 Example Usage: 11141 .vb 11142 extern PetscErrorCode usermult(Mat, Vec, Vec); 11143 11144 PetscCall(MatCreateXXX(comm, ..., &A)); 11145 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11146 .ve 11147 11148 Notes: 11149 See the file `include/petscmat.h` for a complete list of matrix 11150 operations, which all have the form MATOP_<OPERATION>, where 11151 <OPERATION> is the name (in all capital letters) of the 11152 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11153 11154 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11155 sequence as the usual matrix interface routines, since they 11156 are intended to be accessed via the usual matrix interface 11157 routines, e.g., 11158 .vb 11159 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11160 .ve 11161 11162 In particular each function MUST return `PETSC_SUCCESS` on success and 11163 nonzero on failure. 11164 11165 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11166 11167 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11168 @*/ 11169 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11170 { 11171 PetscFunctionBegin; 11172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11173 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11174 (((void (**)(void))mat->ops)[op]) = f; 11175 PetscFunctionReturn(PETSC_SUCCESS); 11176 } 11177 11178 /*@C 11179 MatGetOperation - Gets a matrix operation for any matrix type. 11180 11181 Not Collective 11182 11183 Input Parameters: 11184 + mat - the matrix 11185 - op - the name of the operation 11186 11187 Output Parameter: 11188 . f - the function that provides the operation 11189 11190 Level: developer 11191 11192 Example Usage: 11193 .vb 11194 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11195 11196 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11197 .ve 11198 11199 Notes: 11200 See the file include/petscmat.h for a complete list of matrix 11201 operations, which all have the form MATOP_<OPERATION>, where 11202 <OPERATION> is the name (in all capital letters) of the 11203 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11204 11205 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11206 11207 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11208 @*/ 11209 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11210 { 11211 PetscFunctionBegin; 11212 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11213 *f = (((void (**)(void))mat->ops)[op]); 11214 PetscFunctionReturn(PETSC_SUCCESS); 11215 } 11216 11217 /*@ 11218 MatHasOperation - Determines whether the given matrix supports the particular operation. 11219 11220 Not Collective 11221 11222 Input Parameters: 11223 + mat - the matrix 11224 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11225 11226 Output Parameter: 11227 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11228 11229 Level: advanced 11230 11231 Note: 11232 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11233 11234 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11235 @*/ 11236 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11237 { 11238 PetscFunctionBegin; 11239 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11240 PetscAssertPointer(has, 3); 11241 if (mat->ops->hasoperation) { 11242 PetscUseTypeMethod(mat, hasoperation, op, has); 11243 } else { 11244 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11245 else { 11246 *has = PETSC_FALSE; 11247 if (op == MATOP_CREATE_SUBMATRIX) { 11248 PetscMPIInt size; 11249 11250 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11251 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11252 } 11253 } 11254 } 11255 PetscFunctionReturn(PETSC_SUCCESS); 11256 } 11257 11258 /*@ 11259 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11260 11261 Collective 11262 11263 Input Parameter: 11264 . mat - the matrix 11265 11266 Output Parameter: 11267 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11268 11269 Level: beginner 11270 11271 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11272 @*/ 11273 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11274 { 11275 PetscFunctionBegin; 11276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11277 PetscValidType(mat, 1); 11278 PetscAssertPointer(cong, 2); 11279 if (!mat->rmap || !mat->cmap) { 11280 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11281 PetscFunctionReturn(PETSC_SUCCESS); 11282 } 11283 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11284 PetscCall(PetscLayoutSetUp(mat->rmap)); 11285 PetscCall(PetscLayoutSetUp(mat->cmap)); 11286 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11287 if (*cong) mat->congruentlayouts = 1; 11288 else mat->congruentlayouts = 0; 11289 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11290 PetscFunctionReturn(PETSC_SUCCESS); 11291 } 11292 11293 PetscErrorCode MatSetInf(Mat A) 11294 { 11295 PetscFunctionBegin; 11296 PetscUseTypeMethod(A, setinf); 11297 PetscFunctionReturn(PETSC_SUCCESS); 11298 } 11299 11300 /*@C 11301 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 11302 and possibly removes small values from the graph structure. 11303 11304 Collective 11305 11306 Input Parameters: 11307 + A - the matrix 11308 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11309 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11310 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11311 . num_idx - size of 'index' array 11312 - index - array of block indices to use for graph strength of connection weight 11313 11314 Output Parameter: 11315 . graph - the resulting graph 11316 11317 Level: advanced 11318 11319 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11320 @*/ 11321 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11322 { 11323 PetscFunctionBegin; 11324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11325 PetscValidType(A, 1); 11326 PetscValidLogicalCollectiveBool(A, scale, 3); 11327 PetscAssertPointer(graph, 7); 11328 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11329 PetscFunctionReturn(PETSC_SUCCESS); 11330 } 11331 11332 /*@ 11333 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11334 meaning the same memory is used for the matrix, and no new memory is allocated. 11335 11336 Collective 11337 11338 Input Parameters: 11339 + A - the matrix 11340 - 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 11341 11342 Level: intermediate 11343 11344 Developer Note: 11345 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11346 of the arrays in the data structure are unneeded. 11347 11348 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11349 @*/ 11350 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11351 { 11352 PetscFunctionBegin; 11353 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11354 PetscUseTypeMethod(A, eliminatezeros, keep); 11355 PetscFunctionReturn(PETSC_SUCCESS); 11356 } 11357