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 PETSC_INTERN 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; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetSize(mat, &N, NULL)); 207 PetscCall(MatGetLocalSize(mat, &n, NULL)); 208 PetscCall(VecSet(l, 0.0)); 209 PetscCall(VecSetRandom(r, NULL)); 210 PetscCall(MatMult(mat, r, l)); 211 PetscCall(VecGetArrayRead(l, &al)); 212 } else { /* nonzero columns */ 213 PetscCall(MatGetSize(mat, NULL, &N)); 214 PetscCall(MatGetLocalSize(mat, NULL, &n)); 215 PetscCall(VecSet(r, 0.0)); 216 PetscCall(VecSetRandom(l, NULL)); 217 PetscCall(MatMultTranspose(mat, l, r)); 218 PetscCall(VecGetArrayRead(r, &al)); 219 } 220 if (tol <= 0.0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nz++; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nz++; 226 } 227 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 228 if (gnz != N) { 229 PetscInt *nzr; 230 PetscCall(PetscMalloc1(nz, &nzr)); 231 if (nz) { 232 if (tol < 0) { 233 for (i = 0, nz = 0; i < n; i++) 234 if (al[i] != 0.0) nzr[nz++] = i; 235 } else { 236 for (i = 0, nz = 0; i < n; i++) 237 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 238 } 239 } 240 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 241 } else *nonzero = NULL; 242 if (!cols) { /* nonzero rows */ 243 PetscCall(VecRestoreArrayRead(l, &al)); 244 } else { 245 PetscCall(VecRestoreArrayRead(r, &al)); 246 } 247 PetscCall(VecDestroy(&l)); 248 PetscCall(VecDestroy(&r)); 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 /*@ 253 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 254 255 Input Parameter: 256 . mat - the matrix 257 258 Output Parameter: 259 . keptrows - the rows that are not completely zero 260 261 Level: intermediate 262 263 Note: 264 `keptrows` is set to `NULL` if all rows are nonzero. 265 266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 267 @*/ 268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 269 { 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 272 PetscValidType(mat, 1); 273 PetscAssertPointer(keptrows, 2); 274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 276 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 277 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 278 PetscFunctionReturn(PETSC_SUCCESS); 279 } 280 281 /*@ 282 MatFindZeroRows - Locate all rows that are completely zero in the matrix 283 284 Input Parameter: 285 . mat - the matrix 286 287 Output Parameter: 288 . zerorows - the rows that are completely zero 289 290 Level: intermediate 291 292 Note: 293 `zerorows` is set to `NULL` if no rows are zero. 294 295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 296 @*/ 297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 298 { 299 IS keptrows; 300 PetscInt m, n; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 304 PetscValidType(mat, 1); 305 PetscAssertPointer(zerorows, 2); 306 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 307 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 308 In keeping with this convention, we set zerorows to NULL if there are no zero 309 rows. */ 310 if (keptrows == NULL) { 311 *zerorows = NULL; 312 } else { 313 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 314 PetscCall(ISComplement(keptrows, m, n, zerorows)); 315 PetscCall(ISDestroy(&keptrows)); 316 } 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 322 323 Not Collective 324 325 Input Parameter: 326 . A - the matrix 327 328 Output Parameter: 329 . a - the diagonal part (which is a SEQUENTIAL matrix) 330 331 Level: advanced 332 333 Notes: 334 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 335 336 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 337 338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 339 @*/ 340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 344 PetscValidType(A, 1); 345 PetscAssertPointer(a, 2); 346 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 347 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 348 else { 349 PetscMPIInt size; 350 351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 352 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 353 *a = A; 354 } 355 PetscFunctionReturn(PETSC_SUCCESS); 356 } 357 358 /*@ 359 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 360 361 Collective 362 363 Input Parameter: 364 . mat - the matrix 365 366 Output Parameter: 367 . trace - the sum of the diagonal entries 368 369 Level: advanced 370 371 .seealso: [](ch_matrices), `Mat` 372 @*/ 373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 374 { 375 Vec diag; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 379 PetscAssertPointer(trace, 2); 380 PetscCall(MatCreateVecs(mat, &diag, NULL)); 381 PetscCall(MatGetDiagonal(mat, diag)); 382 PetscCall(VecSum(diag, trace)); 383 PetscCall(VecDestroy(&diag)); 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 /*@ 388 MatRealPart - Zeros out the imaginary part of the matrix 389 390 Logically Collective 391 392 Input Parameter: 393 . mat - the matrix 394 395 Level: advanced 396 397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 398 @*/ 399 PetscErrorCode MatRealPart(Mat mat) 400 { 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 403 PetscValidType(mat, 1); 404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406 MatCheckPreallocated(mat, 1); 407 PetscUseTypeMethod(mat, realpart); 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 /*@C 412 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 413 414 Collective 415 416 Input Parameter: 417 . mat - the matrix 418 419 Output Parameters: 420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 421 - ghosts - the global indices of the ghost points 422 423 Level: advanced 424 425 Note: 426 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 427 428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 429 @*/ 430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 431 { 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 434 PetscValidType(mat, 1); 435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 437 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 438 else { 439 if (nghosts) *nghosts = 0; 440 if (ghosts) *ghosts = NULL; 441 } 442 PetscFunctionReturn(PETSC_SUCCESS); 443 } 444 445 /*@ 446 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 447 448 Logically Collective 449 450 Input Parameter: 451 . mat - the matrix 452 453 Level: advanced 454 455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 456 @*/ 457 PetscErrorCode MatImaginaryPart(Mat mat) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 461 PetscValidType(mat, 1); 462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 464 MatCheckPreallocated(mat, 1); 465 PetscUseTypeMethod(mat, imaginarypart); 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 /*@ 470 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 471 472 Not Collective 473 474 Input Parameter: 475 . mat - the matrix 476 477 Output Parameters: 478 + missing - is any diagonal entry missing 479 - dd - first diagonal entry that is missing (optional) on this process 480 481 Level: advanced 482 483 Note: 484 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 485 486 .seealso: [](ch_matrices), `Mat` 487 @*/ 488 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 489 { 490 PetscFunctionBegin; 491 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 492 PetscValidType(mat, 1); 493 PetscAssertPointer(missing, 2); 494 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 495 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 496 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 497 PetscFunctionReturn(PETSC_SUCCESS); 498 } 499 500 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 501 /*@C 502 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 503 for each row that you get to ensure that your application does 504 not bleed memory. 505 506 Not Collective 507 508 Input Parameters: 509 + mat - the matrix 510 - row - the row to get 511 512 Output Parameters: 513 + ncols - if not `NULL`, the number of nonzeros in `row` 514 . cols - if not `NULL`, the column numbers 515 - vals - if not `NULL`, the numerical values 516 517 Level: advanced 518 519 Notes: 520 This routine is provided for people who need to have direct access 521 to the structure of a matrix. We hope that we provide enough 522 high-level matrix routines that few users will need it. 523 524 `MatGetRow()` always returns 0-based column indices, regardless of 525 whether the internal representation is 0-based (default) or 1-based. 526 527 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 528 not wish to extract these quantities. 529 530 The user can only examine the values extracted with `MatGetRow()`; 531 the values CANNOT be altered. To change the matrix entries, one 532 must use `MatSetValues()`. 533 534 You can only have one call to `MatGetRow()` outstanding for a particular 535 matrix at a time, per processor. `MatGetRow()` can only obtain rows 536 associated with the given processor, it cannot get rows from the 537 other processors; for that we suggest using `MatCreateSubMatrices()`, then 538 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 539 is in the global number of rows. 540 541 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 542 543 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 544 545 Fortran Note: 546 The calling sequence is 547 .vb 548 MatGetRow(matrix,row,ncols,cols,values,ierr) 549 Mat matrix (input) 550 integer row (input) 551 integer ncols (output) 552 integer cols(maxcols) (output) 553 double precision (or double complex) values(maxcols) output 554 .ve 555 where maxcols >= maximum nonzeros in any row of the matrix. 556 557 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 558 @*/ 559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 560 { 561 PetscInt incols; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 565 PetscValidType(mat, 1); 566 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 567 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 568 MatCheckPreallocated(mat, 1); 569 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); 570 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 571 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 572 if (ncols) *ncols = incols; 573 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 574 PetscFunctionReturn(PETSC_SUCCESS); 575 } 576 577 /*@ 578 MatConjugate - replaces the matrix values with their complex conjugates 579 580 Logically Collective 581 582 Input Parameter: 583 . mat - the matrix 584 585 Level: advanced 586 587 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 588 @*/ 589 PetscErrorCode MatConjugate(Mat mat) 590 { 591 PetscFunctionBegin; 592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 594 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 595 PetscUseTypeMethod(mat, conjugate); 596 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 597 } 598 PetscFunctionReturn(PETSC_SUCCESS); 599 } 600 601 /*@C 602 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 603 604 Not Collective 605 606 Input Parameters: 607 + mat - the matrix 608 . row - the row to get 609 . ncols - the number of nonzeros 610 . cols - the columns of the nonzeros 611 - vals - if nonzero the column values 612 613 Level: advanced 614 615 Notes: 616 This routine should be called after you have finished examining the entries. 617 618 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 619 us of the array after it has been restored. If you pass `NULL`, it will 620 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 621 622 Fortran Notes: 623 The calling sequence is 624 .vb 625 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 626 Mat matrix (input) 627 integer row (input) 628 integer ncols (output) 629 integer cols(maxcols) (output) 630 double precision (or double complex) values(maxcols) output 631 .ve 632 Where maxcols >= maximum nonzeros in any row of the matrix. 633 634 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 635 before another call to `MatGetRow()` can be made. 636 637 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 638 @*/ 639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 640 { 641 PetscFunctionBegin; 642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 643 if (ncols) PetscAssertPointer(ncols, 3); 644 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 645 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 646 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 647 if (ncols) *ncols = 0; 648 if (cols) *cols = NULL; 649 if (vals) *vals = NULL; 650 PetscFunctionReturn(PETSC_SUCCESS); 651 } 652 653 /*@ 654 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 655 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 656 657 Not Collective 658 659 Input Parameter: 660 . mat - the matrix 661 662 Level: advanced 663 664 Note: 665 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. 666 667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 668 @*/ 669 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 670 { 671 PetscFunctionBegin; 672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 673 PetscValidType(mat, 1); 674 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 675 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 676 MatCheckPreallocated(mat, 1); 677 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 678 PetscUseTypeMethod(mat, getrowuppertriangular); 679 PetscFunctionReturn(PETSC_SUCCESS); 680 } 681 682 /*@ 683 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 684 685 Not Collective 686 687 Input Parameter: 688 . mat - the matrix 689 690 Level: advanced 691 692 Note: 693 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 694 695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 696 @*/ 697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 698 { 699 PetscFunctionBegin; 700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 701 PetscValidType(mat, 1); 702 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 703 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 704 MatCheckPreallocated(mat, 1); 705 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 706 PetscUseTypeMethod(mat, restorerowuppertriangular); 707 PetscFunctionReturn(PETSC_SUCCESS); 708 } 709 710 /*@C 711 MatSetOptionsPrefix - Sets the prefix used for searching for all 712 `Mat` options in the database. 713 714 Logically Collective 715 716 Input Parameters: 717 + A - the matrix 718 - prefix - the prefix to prepend to all option names 719 720 Level: advanced 721 722 Notes: 723 A hyphen (-) must NOT be given at the beginning of the prefix name. 724 The first character of all runtime options is AUTOMATICALLY the hyphen. 725 726 This is NOT used for options for the factorization of the matrix. Normally the 727 prefix is automatically passed in from the PC calling the factorization. To set 728 it directly use `MatSetOptionsPrefixFactor()` 729 730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 731 @*/ 732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 733 { 734 PetscFunctionBegin; 735 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 736 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 737 PetscFunctionReturn(PETSC_SUCCESS); 738 } 739 740 /*@C 741 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 742 for matrices created with `MatGetFactor()` 743 744 Logically Collective 745 746 Input Parameters: 747 + A - the matrix 748 - prefix - the prefix to prepend to all option names for the factored matrix 749 750 Level: developer 751 752 Notes: 753 A hyphen (-) must NOT be given at the beginning of the prefix name. 754 The first character of all runtime options is AUTOMATICALLY the hyphen. 755 756 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 757 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 758 759 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 760 @*/ 761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 762 { 763 PetscFunctionBegin; 764 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 765 if (prefix) { 766 PetscAssertPointer(prefix, 2); 767 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 768 if (prefix != A->factorprefix) { 769 PetscCall(PetscFree(A->factorprefix)); 770 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 771 } 772 } else PetscCall(PetscFree(A->factorprefix)); 773 PetscFunctionReturn(PETSC_SUCCESS); 774 } 775 776 /*@C 777 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 778 for matrices created with `MatGetFactor()` 779 780 Logically Collective 781 782 Input Parameters: 783 + A - the matrix 784 - prefix - the prefix to prepend to all option names for the factored matrix 785 786 Level: developer 787 788 Notes: 789 A hyphen (-) must NOT be given at the beginning of the prefix name. 790 The first character of all runtime options is AUTOMATICALLY the hyphen. 791 792 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 793 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 794 795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 796 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 797 `MatSetOptionsPrefix()` 798 @*/ 799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 800 { 801 size_t len1, len2, new_len; 802 803 PetscFunctionBegin; 804 PetscValidHeader(A, 1); 805 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 806 if (!A->factorprefix) { 807 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 808 PetscFunctionReturn(PETSC_SUCCESS); 809 } 810 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 811 812 PetscCall(PetscStrlen(A->factorprefix, &len1)); 813 PetscCall(PetscStrlen(prefix, &len2)); 814 new_len = len1 + len2 + 1; 815 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 816 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 817 PetscFunctionReturn(PETSC_SUCCESS); 818 } 819 820 /*@C 821 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 822 matrix options in the database. 823 824 Logically Collective 825 826 Input Parameters: 827 + A - the matrix 828 - prefix - the prefix to prepend to all option names 829 830 Level: advanced 831 832 Note: 833 A hyphen (-) must NOT be given at the beginning of the prefix name. 834 The first character of all runtime options is AUTOMATICALLY the hyphen. 835 836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 837 @*/ 838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 839 { 840 PetscFunctionBegin; 841 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 842 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 843 PetscFunctionReturn(PETSC_SUCCESS); 844 } 845 846 /*@C 847 MatGetOptionsPrefix - Gets the prefix used for searching for all 848 matrix options in the database. 849 850 Not Collective 851 852 Input Parameter: 853 . A - the matrix 854 855 Output Parameter: 856 . prefix - pointer to the prefix string used 857 858 Level: advanced 859 860 Fortran Note: 861 The user should pass in a string `prefix` of 862 sufficient length to hold the prefix. 863 864 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 865 @*/ 866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 867 { 868 PetscFunctionBegin; 869 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 870 PetscAssertPointer(prefix, 2); 871 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 872 PetscFunctionReturn(PETSC_SUCCESS); 873 } 874 875 /*@ 876 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 877 878 Collective 879 880 Input Parameter: 881 . A - the matrix 882 883 Level: beginner 884 885 Notes: 886 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 887 888 Users can reset the preallocation to access the original memory. 889 890 Currently only supported for `MATAIJ` matrices. 891 892 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 893 @*/ 894 PetscErrorCode MatResetPreallocation(Mat A) 895 { 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 898 PetscValidType(A, 1); 899 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 900 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 901 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 902 PetscFunctionReturn(PETSC_SUCCESS); 903 } 904 905 /*@ 906 MatSetUp - Sets up the internal matrix data structures for later use. 907 908 Collective 909 910 Input Parameter: 911 . A - the matrix 912 913 Level: intermediate 914 915 Notes: 916 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 917 setting values in the matrix. 918 919 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 920 921 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 922 @*/ 923 PetscErrorCode MatSetUp(Mat A) 924 { 925 PetscFunctionBegin; 926 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 927 if (!((PetscObject)A)->type_name) { 928 PetscMPIInt size; 929 930 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 931 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 932 } 933 if (!A->preallocated) PetscTryTypeMethod(A, setup); 934 PetscCall(PetscLayoutSetUp(A->rmap)); 935 PetscCall(PetscLayoutSetUp(A->cmap)); 936 A->preallocated = PETSC_TRUE; 937 PetscFunctionReturn(PETSC_SUCCESS); 938 } 939 940 #if defined(PETSC_HAVE_SAWS) 941 #include <petscviewersaws.h> 942 #endif 943 944 /* 945 If threadsafety is on extraneous matrices may be printed 946 947 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 948 */ 949 #if !defined(PETSC_HAVE_THREADSAFETY) 950 static PetscInt insidematview = 0; 951 #endif 952 953 /*@C 954 MatViewFromOptions - View properties of the matrix based on options set in the options database 955 956 Collective 957 958 Input Parameters: 959 + A - the matrix 960 . obj - optional additional object that provides the options prefix to use 961 - name - command line option 962 963 Options Database Key: 964 . -mat_view [viewertype]:... - the viewer and its options 965 966 Level: intermediate 967 968 Note: 969 .vb 970 If no value is provided ascii:stdout is used 971 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 972 for example ascii::ascii_info prints just the information about the object not all details 973 unless :append is given filename opens in write mode, overwriting what was already there 974 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 975 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 976 socket[:port] defaults to the standard output port 977 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 978 .ve 979 980 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 981 @*/ 982 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 983 { 984 PetscFunctionBegin; 985 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 986 #if !defined(PETSC_HAVE_THREADSAFETY) 987 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 988 #endif 989 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 990 PetscFunctionReturn(PETSC_SUCCESS); 991 } 992 993 /*@C 994 MatView - display information about a matrix in a variety ways 995 996 Collective 997 998 Input Parameters: 999 + mat - the matrix 1000 - viewer - visualization context 1001 1002 Options Database Keys: 1003 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1004 . -mat_view ::ascii_info_detail - Prints more detailed info 1005 . -mat_view - Prints matrix in ASCII format 1006 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1007 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1008 . -display <name> - Sets display name (default is host) 1009 . -draw_pause <sec> - Sets number of seconds to pause after display 1010 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1011 . -viewer_socket_machine <machine> - - 1012 . -viewer_socket_port <port> - - 1013 . -mat_view binary - save matrix to file in binary format 1014 - -viewer_binary_filename <name> - - 1015 1016 Level: beginner 1017 1018 Notes: 1019 The available visualization contexts include 1020 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1021 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1022 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1023 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1024 1025 The user can open alternative visualization contexts with 1026 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1027 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1028 specified file; corresponding input uses `MatLoad()` 1029 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1030 an X window display 1031 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1032 Currently only the `MATSEQDENSE` and `MATAIJ` 1033 matrix types support the Socket viewer. 1034 1035 The user can call `PetscViewerPushFormat()` to specify the output 1036 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1037 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1038 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1039 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1040 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1041 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1042 format common among all matrix types 1043 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1044 format (which is in many cases the same as the default) 1045 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1046 size and structure (not the matrix entries) 1047 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1048 the matrix structure 1049 1050 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1051 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1052 1053 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1054 1055 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1056 viewer is used. 1057 1058 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1059 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1060 1061 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1062 and then use the following mouse functions. 1063 .vb 1064 left mouse: zoom in 1065 middle mouse: zoom out 1066 right mouse: continue with the simulation 1067 .ve 1068 1069 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1070 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1071 @*/ 1072 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1073 { 1074 PetscInt rows, cols, rbs, cbs; 1075 PetscBool isascii, isstring, issaws; 1076 PetscViewerFormat format; 1077 PetscMPIInt size; 1078 1079 PetscFunctionBegin; 1080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1081 PetscValidType(mat, 1); 1082 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1083 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1084 PetscCheckSameComm(mat, 1, viewer, 2); 1085 1086 PetscCall(PetscViewerGetFormat(viewer, &format)); 1087 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1088 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1089 1090 #if !defined(PETSC_HAVE_THREADSAFETY) 1091 insidematview++; 1092 #endif 1093 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1094 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1096 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"); 1097 1098 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1099 if (isascii) { 1100 if (!mat->preallocated) { 1101 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1102 #if !defined(PETSC_HAVE_THREADSAFETY) 1103 insidematview--; 1104 #endif 1105 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1106 PetscFunctionReturn(PETSC_SUCCESS); 1107 } 1108 if (!mat->assembled) { 1109 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1110 #if !defined(PETSC_HAVE_THREADSAFETY) 1111 insidematview--; 1112 #endif 1113 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1114 PetscFunctionReturn(PETSC_SUCCESS); 1115 } 1116 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1117 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1118 MatNullSpace nullsp, transnullsp; 1119 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatGetSize(mat, &rows, &cols)); 1122 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1123 if (rbs != 1 || cbs != 1) { 1124 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1125 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1126 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1127 if (mat->factortype) { 1128 MatSolverType solver; 1129 PetscCall(MatFactorGetSolverType(mat, &solver)); 1130 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1131 } 1132 if (mat->ops->getinfo) { 1133 MatInfo info; 1134 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1135 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1136 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1137 } 1138 PetscCall(MatGetNullSpace(mat, &nullsp)); 1139 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1140 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1141 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1142 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1143 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1144 PetscCall(PetscViewerASCIIPushTab(viewer)); 1145 PetscCall(MatProductView(mat, viewer)); 1146 PetscCall(PetscViewerASCIIPopTab(viewer)); 1147 } 1148 } else if (issaws) { 1149 #if defined(PETSC_HAVE_SAWS) 1150 PetscMPIInt rank; 1151 1152 PetscCall(PetscObjectName((PetscObject)mat)); 1153 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1154 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1155 #endif 1156 } else if (isstring) { 1157 const char *type; 1158 PetscCall(MatGetType(mat, &type)); 1159 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1160 PetscTryTypeMethod(mat, view, viewer); 1161 } 1162 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1163 PetscCall(PetscViewerASCIIPushTab(viewer)); 1164 PetscUseTypeMethod(mat, viewnative, viewer); 1165 PetscCall(PetscViewerASCIIPopTab(viewer)); 1166 } else if (mat->ops->view) { 1167 PetscCall(PetscViewerASCIIPushTab(viewer)); 1168 PetscUseTypeMethod(mat, view, viewer); 1169 PetscCall(PetscViewerASCIIPopTab(viewer)); 1170 } 1171 if (isascii) { 1172 PetscCall(PetscViewerGetFormat(viewer, &format)); 1173 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1174 } 1175 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1176 #if !defined(PETSC_HAVE_THREADSAFETY) 1177 insidematview--; 1178 #endif 1179 PetscFunctionReturn(PETSC_SUCCESS); 1180 } 1181 1182 #if defined(PETSC_USE_DEBUG) 1183 #include <../src/sys/totalview/tv_data_display.h> 1184 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1185 { 1186 TV_add_row("Local rows", "int", &mat->rmap->n); 1187 TV_add_row("Local columns", "int", &mat->cmap->n); 1188 TV_add_row("Global rows", "int", &mat->rmap->N); 1189 TV_add_row("Global columns", "int", &mat->cmap->N); 1190 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1191 return TV_format_OK; 1192 } 1193 #endif 1194 1195 /*@C 1196 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1197 with `MatView()`. The matrix format is determined from the options database. 1198 Generates a parallel MPI matrix if the communicator has more than one 1199 processor. The default matrix type is `MATAIJ`. 1200 1201 Collective 1202 1203 Input Parameters: 1204 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1205 or some related function before a call to `MatLoad()` 1206 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1207 1208 Options Database Key: 1209 . -matload_block_size <bs> - set block size 1210 1211 Level: beginner 1212 1213 Notes: 1214 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1215 `Mat` before calling this routine if you wish to set it from the options database. 1216 1217 `MatLoad()` automatically loads into the options database any options 1218 given in the file filename.info where filename is the name of the file 1219 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1220 file will be ignored if you use the -viewer_binary_skip_info option. 1221 1222 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1223 sets the default matrix type AIJ and sets the local and global sizes. 1224 If type and/or size is already set, then the same are used. 1225 1226 In parallel, each processor can load a subset of rows (or the 1227 entire matrix). This routine is especially useful when a large 1228 matrix is stored on disk and only part of it is desired on each 1229 processor. For example, a parallel solver may access only some of 1230 the rows from each processor. The algorithm used here reads 1231 relatively small blocks of data rather than reading the entire 1232 matrix and then subsetting it. 1233 1234 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1235 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1236 or the sequence like 1237 .vb 1238 `PetscViewer` v; 1239 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1240 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1241 `PetscViewerSetFromOptions`(v); 1242 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1243 `PetscViewerFileSetName`(v,"datafile"); 1244 .ve 1245 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1246 $ -viewer_type {binary, hdf5} 1247 1248 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1249 and src/mat/tutorials/ex10.c with the second approach. 1250 1251 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1252 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1255 1256 Most users should not need to know the details of the binary storage 1257 format, since `MatLoad()` and `MatView()` completely hide these details. 1258 But for anyone who is interested, the standard binary matrix storage 1259 format is 1260 1261 .vb 1262 PetscInt MAT_FILE_CLASSID 1263 PetscInt number of rows 1264 PetscInt number of columns 1265 PetscInt total number of nonzeros 1266 PetscInt *number nonzeros in each row 1267 PetscInt *column indices of all nonzeros (starting index is zero) 1268 PetscScalar *values of all nonzeros 1269 .ve 1270 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1271 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 1272 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1273 1274 PETSc automatically does the byte swapping for 1275 machines that store the bytes reversed. Thus if you write your own binary 1276 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1277 and `PetscBinaryWrite()` to see how this may be done. 1278 1279 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1280 Each processor's chunk is loaded independently by its owning MPI process. 1281 Multiple objects, both matrices and vectors, can be stored within the same file. 1282 They are looked up by their PetscObject name. 1283 1284 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1285 by default the same structure and naming of the AIJ arrays and column count 1286 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1287 $ save example.mat A b -v7.3 1288 can be directly read by this routine (see Reference 1 for details). 1289 1290 Depending on your MATLAB version, this format might be a default, 1291 otherwise you can set it as default in Preferences. 1292 1293 Unless -nocompression flag is used to save the file in MATLAB, 1294 PETSc must be configured with ZLIB package. 1295 1296 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1297 1298 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1299 1300 Corresponding `MatView()` is not yet implemented. 1301 1302 The loaded matrix is actually a transpose of the original one in MATLAB, 1303 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1304 With this format, matrix is automatically transposed by PETSc, 1305 unless the matrix is marked as SPD or symmetric 1306 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1307 1308 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1309 1310 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1311 @*/ 1312 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1313 { 1314 PetscBool flg; 1315 1316 PetscFunctionBegin; 1317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1318 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1319 1320 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1321 1322 flg = PETSC_FALSE; 1323 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1324 if (flg) { 1325 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1326 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1327 } 1328 flg = PETSC_FALSE; 1329 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1330 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1331 1332 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1333 PetscUseTypeMethod(mat, load, viewer); 1334 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 1338 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1339 { 1340 Mat_Redundant *redund = *redundant; 1341 1342 PetscFunctionBegin; 1343 if (redund) { 1344 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1345 PetscCall(ISDestroy(&redund->isrow)); 1346 PetscCall(ISDestroy(&redund->iscol)); 1347 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1348 } else { 1349 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1350 PetscCall(PetscFree(redund->sbuf_j)); 1351 PetscCall(PetscFree(redund->sbuf_a)); 1352 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1353 PetscCall(PetscFree(redund->rbuf_j[i])); 1354 PetscCall(PetscFree(redund->rbuf_a[i])); 1355 } 1356 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1357 } 1358 1359 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1360 PetscCall(PetscFree(redund)); 1361 } 1362 PetscFunctionReturn(PETSC_SUCCESS); 1363 } 1364 1365 /*@C 1366 MatDestroy - Frees space taken by a matrix. 1367 1368 Collective 1369 1370 Input Parameter: 1371 . A - the matrix 1372 1373 Level: beginner 1374 1375 Developer Note: 1376 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1377 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1378 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1379 if changes are needed here. 1380 1381 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1382 @*/ 1383 PetscErrorCode MatDestroy(Mat *A) 1384 { 1385 PetscFunctionBegin; 1386 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1387 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1388 if (--((PetscObject)(*A))->refct > 0) { 1389 *A = NULL; 1390 PetscFunctionReturn(PETSC_SUCCESS); 1391 } 1392 1393 /* if memory was published with SAWs then destroy it */ 1394 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1395 PetscTryTypeMethod((*A), destroy); 1396 1397 PetscCall(PetscFree((*A)->factorprefix)); 1398 PetscCall(PetscFree((*A)->defaultvectype)); 1399 PetscCall(PetscFree((*A)->defaultrandtype)); 1400 PetscCall(PetscFree((*A)->bsizes)); 1401 PetscCall(PetscFree((*A)->solvertype)); 1402 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1403 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1404 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1405 PetscCall(MatProductClear(*A)); 1406 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1407 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1408 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1409 PetscCall(MatDestroy(&(*A)->schur)); 1410 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1411 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1412 PetscCall(PetscHeaderDestroy(A)); 1413 PetscFunctionReturn(PETSC_SUCCESS); 1414 } 1415 1416 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1417 /*@C 1418 MatSetValues - Inserts or adds a block of values into a matrix. 1419 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1420 MUST be called after all calls to `MatSetValues()` have been completed. 1421 1422 Not Collective 1423 1424 Input Parameters: 1425 + mat - the matrix 1426 . v - a logically two-dimensional array of values 1427 . m - the number of rows 1428 . idxm - the global indices of the rows 1429 . n - the number of columns 1430 . idxn - the global indices of the columns 1431 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1432 1433 Level: beginner 1434 1435 Notes: 1436 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1437 1438 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1439 options cannot be mixed without intervening calls to the assembly 1440 routines. 1441 1442 `MatSetValues()` uses 0-based row and column numbers in Fortran 1443 as well as in C. 1444 1445 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1446 simply ignored. This allows easily inserting element stiffness matrices 1447 with homogeneous Dirichlet boundary conditions that you don't want represented 1448 in the matrix. 1449 1450 Efficiency Alert: 1451 The routine `MatSetValuesBlocked()` may offer much better efficiency 1452 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1453 1454 Developer Note: 1455 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1456 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1457 1458 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1459 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1460 @*/ 1461 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1462 { 1463 PetscFunctionBeginHot; 1464 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1465 PetscValidType(mat, 1); 1466 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1467 PetscAssertPointer(idxm, 3); 1468 PetscAssertPointer(idxn, 5); 1469 MatCheckPreallocated(mat, 1); 1470 1471 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1472 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1473 1474 if (PetscDefined(USE_DEBUG)) { 1475 PetscInt i, j; 1476 1477 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1478 for (i = 0; i < m; i++) { 1479 for (j = 0; j < n; j++) { 1480 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1481 #if defined(PETSC_USE_COMPLEX) 1482 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]); 1483 #else 1484 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]); 1485 #endif 1486 } 1487 } 1488 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); 1489 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); 1490 } 1491 1492 if (mat->assembled) { 1493 mat->was_assembled = PETSC_TRUE; 1494 mat->assembled = PETSC_FALSE; 1495 } 1496 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1497 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1498 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1499 PetscFunctionReturn(PETSC_SUCCESS); 1500 } 1501 1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1503 /*@C 1504 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1505 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1506 MUST be called after all calls to `MatSetValues()` have been completed. 1507 1508 Not Collective 1509 1510 Input Parameters: 1511 + mat - the matrix 1512 . v - a logically two-dimensional array of values 1513 . ism - the rows to provide 1514 . isn - the columns to provide 1515 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1516 1517 Level: beginner 1518 1519 Notes: 1520 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1521 1522 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1523 options cannot be mixed without intervening calls to the assembly 1524 routines. 1525 1526 `MatSetValues()` uses 0-based row and column numbers in Fortran 1527 as well as in C. 1528 1529 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1530 simply ignored. This allows easily inserting element stiffness matrices 1531 with homogeneous Dirichlet boundary conditions that you don't want represented 1532 in the matrix. 1533 1534 Efficiency Alert: 1535 The routine `MatSetValuesBlocked()` may offer much better efficiency 1536 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1537 1538 This is currently not optimized for any particular `ISType` 1539 1540 Developer Note: 1541 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1542 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1543 1544 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1545 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1546 @*/ 1547 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1548 { 1549 PetscInt m, n; 1550 const PetscInt *rows, *cols; 1551 1552 PetscFunctionBeginHot; 1553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1554 PetscCall(ISGetIndices(ism, &rows)); 1555 PetscCall(ISGetIndices(isn, &cols)); 1556 PetscCall(ISGetLocalSize(ism, &m)); 1557 PetscCall(ISGetLocalSize(isn, &n)); 1558 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1559 PetscCall(ISRestoreIndices(ism, &rows)); 1560 PetscCall(ISRestoreIndices(isn, &cols)); 1561 PetscFunctionReturn(PETSC_SUCCESS); 1562 } 1563 1564 /*@ 1565 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1566 values into a matrix 1567 1568 Not Collective 1569 1570 Input Parameters: 1571 + mat - the matrix 1572 . row - the (block) row to set 1573 - v - a logically two-dimensional array of values 1574 1575 Level: intermediate 1576 1577 Notes: 1578 The values, `v`, are column-oriented (for the block version) and sorted 1579 1580 All the nonzero values in `row` must be provided 1581 1582 The matrix must have previously had its column indices set, likely by having been assembled. 1583 1584 `row` must belong to this MPI process 1585 1586 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1587 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1588 @*/ 1589 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1590 { 1591 PetscInt globalrow; 1592 1593 PetscFunctionBegin; 1594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1595 PetscValidType(mat, 1); 1596 PetscAssertPointer(v, 3); 1597 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1598 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1599 PetscFunctionReturn(PETSC_SUCCESS); 1600 } 1601 1602 /*@ 1603 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1604 values into a matrix 1605 1606 Not Collective 1607 1608 Input Parameters: 1609 + mat - the matrix 1610 . row - the (block) row to set 1611 - 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 1612 1613 Level: advanced 1614 1615 Notes: 1616 The values, `v`, are column-oriented for the block version. 1617 1618 All the nonzeros in `row` must be provided 1619 1620 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1621 1622 `row` must belong to this process 1623 1624 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1625 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1626 @*/ 1627 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1628 { 1629 PetscFunctionBeginHot; 1630 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1631 PetscValidType(mat, 1); 1632 MatCheckPreallocated(mat, 1); 1633 PetscAssertPointer(v, 3); 1634 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1635 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1636 mat->insertmode = INSERT_VALUES; 1637 1638 if (mat->assembled) { 1639 mat->was_assembled = PETSC_TRUE; 1640 mat->assembled = PETSC_FALSE; 1641 } 1642 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1643 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1644 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1645 PetscFunctionReturn(PETSC_SUCCESS); 1646 } 1647 1648 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1649 /*@ 1650 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1651 Using structured grid indexing 1652 1653 Not Collective 1654 1655 Input Parameters: 1656 + mat - the matrix 1657 . m - number of rows being entered 1658 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1659 . n - number of columns being entered 1660 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1661 . v - a logically two-dimensional array of values 1662 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1663 1664 Level: beginner 1665 1666 Notes: 1667 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1668 1669 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1670 options cannot be mixed without intervening calls to the assembly 1671 routines. 1672 1673 The grid coordinates are across the entire grid, not just the local portion 1674 1675 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1676 as well as in C. 1677 1678 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1679 1680 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1681 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1682 1683 The columns and rows in the stencil passed in MUST be contained within the 1684 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1685 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1686 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1687 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1688 1689 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1690 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1691 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1692 `DM_BOUNDARY_PERIODIC` boundary type. 1693 1694 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 1695 a single value per point) you can skip filling those indices. 1696 1697 Inspired by the structured grid interface to the HYPRE package 1698 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1699 1700 Efficiency Alert: 1701 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1702 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1703 1704 Fortran Note: 1705 `idxm` and `idxn` should be declared as 1706 $ MatStencil idxm(4,m),idxn(4,n) 1707 and the values inserted using 1708 .vb 1709 idxm(MatStencil_i,1) = i 1710 idxm(MatStencil_j,1) = j 1711 idxm(MatStencil_k,1) = k 1712 idxm(MatStencil_c,1) = c 1713 etc 1714 .ve 1715 1716 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1717 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1718 @*/ 1719 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1720 { 1721 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1722 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1723 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1724 1725 PetscFunctionBegin; 1726 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1728 PetscValidType(mat, 1); 1729 PetscAssertPointer(idxm, 3); 1730 PetscAssertPointer(idxn, 5); 1731 1732 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1733 jdxm = buf; 1734 jdxn = buf + m; 1735 } else { 1736 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1737 jdxm = bufm; 1738 jdxn = bufn; 1739 } 1740 for (i = 0; i < m; i++) { 1741 for (j = 0; j < 3 - sdim; j++) dxm++; 1742 tmp = *dxm++ - starts[0]; 1743 for (j = 0; j < dim - 1; j++) { 1744 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1745 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1746 } 1747 if (mat->stencil.noc) dxm++; 1748 jdxm[i] = tmp; 1749 } 1750 for (i = 0; i < n; i++) { 1751 for (j = 0; j < 3 - sdim; j++) dxn++; 1752 tmp = *dxn++ - starts[0]; 1753 for (j = 0; j < dim - 1; j++) { 1754 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1755 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1756 } 1757 if (mat->stencil.noc) dxn++; 1758 jdxn[i] = tmp; 1759 } 1760 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1761 PetscCall(PetscFree2(bufm, bufn)); 1762 PetscFunctionReturn(PETSC_SUCCESS); 1763 } 1764 1765 /*@ 1766 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1767 Using structured grid indexing 1768 1769 Not Collective 1770 1771 Input Parameters: 1772 + mat - the matrix 1773 . m - number of rows being entered 1774 . idxm - grid coordinates for matrix rows being entered 1775 . n - number of columns being entered 1776 . idxn - grid coordinates for matrix columns being entered 1777 . v - a logically two-dimensional array of values 1778 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1779 1780 Level: beginner 1781 1782 Notes: 1783 By default the values, `v`, are row-oriented and unsorted. 1784 See `MatSetOption()` for other options. 1785 1786 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1787 options cannot be mixed without intervening calls to the assembly 1788 routines. 1789 1790 The grid coordinates are across the entire grid, not just the local portion 1791 1792 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1793 as well as in C. 1794 1795 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1796 1797 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1798 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1799 1800 The columns and rows in the stencil passed in MUST be contained within the 1801 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1802 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1803 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1804 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1805 1806 Negative indices may be passed in idxm and idxn, these rows and columns are 1807 simply ignored. This allows easily inserting element stiffness matrices 1808 with homogeneous Dirichlet boundary conditions that you don't want represented 1809 in the matrix. 1810 1811 Inspired by the structured grid interface to the HYPRE package 1812 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1813 1814 Fortran Note: 1815 `idxm` and `idxn` should be declared as 1816 $ MatStencil idxm(4,m),idxn(4,n) 1817 and the values inserted using 1818 .vb 1819 idxm(MatStencil_i,1) = i 1820 idxm(MatStencil_j,1) = j 1821 idxm(MatStencil_k,1) = k 1822 etc 1823 .ve 1824 1825 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1826 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1827 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1828 @*/ 1829 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1830 { 1831 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1832 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1833 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1834 1835 PetscFunctionBegin; 1836 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1838 PetscValidType(mat, 1); 1839 PetscAssertPointer(idxm, 3); 1840 PetscAssertPointer(idxn, 5); 1841 PetscAssertPointer(v, 6); 1842 1843 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1844 jdxm = buf; 1845 jdxn = buf + m; 1846 } else { 1847 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1848 jdxm = bufm; 1849 jdxn = bufn; 1850 } 1851 for (i = 0; i < m; i++) { 1852 for (j = 0; j < 3 - sdim; j++) dxm++; 1853 tmp = *dxm++ - starts[0]; 1854 for (j = 0; j < sdim - 1; j++) { 1855 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1856 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1857 } 1858 dxm++; 1859 jdxm[i] = tmp; 1860 } 1861 for (i = 0; i < n; i++) { 1862 for (j = 0; j < 3 - sdim; j++) dxn++; 1863 tmp = *dxn++ - starts[0]; 1864 for (j = 0; j < sdim - 1; j++) { 1865 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1866 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1867 } 1868 dxn++; 1869 jdxn[i] = tmp; 1870 } 1871 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1872 PetscCall(PetscFree2(bufm, bufn)); 1873 PetscFunctionReturn(PETSC_SUCCESS); 1874 } 1875 1876 /*@ 1877 MatSetStencil - Sets the grid information for setting values into a matrix via 1878 `MatSetValuesStencil()` 1879 1880 Not Collective 1881 1882 Input Parameters: 1883 + mat - the matrix 1884 . dim - dimension of the grid 1, 2, or 3 1885 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1886 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1887 - dof - number of degrees of freedom per node 1888 1889 Level: beginner 1890 1891 Notes: 1892 Inspired by the structured grid interface to the HYPRE package 1893 (www.llnl.gov/CASC/hyper) 1894 1895 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1896 user. 1897 1898 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1899 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1900 @*/ 1901 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1902 { 1903 PetscFunctionBegin; 1904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1905 PetscAssertPointer(dims, 3); 1906 PetscAssertPointer(starts, 4); 1907 1908 mat->stencil.dim = dim + (dof > 1); 1909 for (PetscInt i = 0; i < dim; i++) { 1910 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1911 mat->stencil.starts[i] = starts[dim - i - 1]; 1912 } 1913 mat->stencil.dims[dim] = dof; 1914 mat->stencil.starts[dim] = 0; 1915 mat->stencil.noc = (PetscBool)(dof == 1); 1916 PetscFunctionReturn(PETSC_SUCCESS); 1917 } 1918 1919 /*@C 1920 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1921 1922 Not Collective 1923 1924 Input Parameters: 1925 + mat - the matrix 1926 . v - a logically two-dimensional array of values 1927 . m - the number of block rows 1928 . idxm - the global block indices 1929 . n - the number of block columns 1930 . idxn - the global block indices 1931 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1932 1933 Level: intermediate 1934 1935 Notes: 1936 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1937 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1938 1939 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1940 NOT the total number of rows/columns; for example, if the block size is 2 and 1941 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1942 The values in idxm would be 1 2; that is the first index for each block divided by 1943 the block size. 1944 1945 You must call `MatSetBlockSize()` when constructing this matrix (before 1946 preallocating it). 1947 1948 By default the values, `v`, are row-oriented, so the layout of 1949 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1950 1951 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1952 options cannot be mixed without intervening calls to the assembly 1953 routines. 1954 1955 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1956 as well as in C. 1957 1958 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1959 simply ignored. This allows easily inserting element stiffness matrices 1960 with homogeneous Dirichlet boundary conditions that you don't want represented 1961 in the matrix. 1962 1963 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1964 internal searching must be done to determine where to place the 1965 data in the matrix storage space. By instead inserting blocks of 1966 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1967 reduced. 1968 1969 Example: 1970 .vb 1971 Suppose m=n=2 and block size(bs) = 2 The array is 1972 1973 1 2 | 3 4 1974 5 6 | 7 8 1975 - - - | - - - 1976 9 10 | 11 12 1977 13 14 | 15 16 1978 1979 v[] should be passed in like 1980 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1981 1982 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1983 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1984 .ve 1985 1986 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1987 @*/ 1988 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1989 { 1990 PetscFunctionBeginHot; 1991 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1992 PetscValidType(mat, 1); 1993 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1994 PetscAssertPointer(idxm, 3); 1995 PetscAssertPointer(idxn, 5); 1996 MatCheckPreallocated(mat, 1); 1997 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1998 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1999 if (PetscDefined(USE_DEBUG)) { 2000 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2001 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2002 } 2003 if (PetscDefined(USE_DEBUG)) { 2004 PetscInt rbs, cbs, M, N, i; 2005 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2006 PetscCall(MatGetSize(mat, &M, &N)); 2007 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); 2008 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); 2009 } 2010 if (mat->assembled) { 2011 mat->was_assembled = PETSC_TRUE; 2012 mat->assembled = PETSC_FALSE; 2013 } 2014 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2015 if (mat->ops->setvaluesblocked) { 2016 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2017 } else { 2018 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2019 PetscInt i, j, bs, cbs; 2020 2021 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2022 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2023 iidxm = buf; 2024 iidxn = buf + m * bs; 2025 } else { 2026 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2027 iidxm = bufr; 2028 iidxn = bufc; 2029 } 2030 for (i = 0; i < m; i++) { 2031 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2032 } 2033 if (m != n || bs != cbs || idxm != idxn) { 2034 for (i = 0; i < n; i++) { 2035 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2036 } 2037 } else iidxn = iidxm; 2038 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2039 PetscCall(PetscFree2(bufr, bufc)); 2040 } 2041 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2042 PetscFunctionReturn(PETSC_SUCCESS); 2043 } 2044 2045 /*@C 2046 MatGetValues - Gets a block of local values from a matrix. 2047 2048 Not Collective; can only return values that are owned by the give process 2049 2050 Input Parameters: 2051 + mat - the matrix 2052 . v - a logically two-dimensional array for storing the values 2053 . m - the number of rows 2054 . idxm - the global indices of the rows 2055 . n - the number of columns 2056 - idxn - the global indices of the columns 2057 2058 Level: advanced 2059 2060 Notes: 2061 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2062 The values, `v`, are then returned in a row-oriented format, 2063 analogous to that used by default in `MatSetValues()`. 2064 2065 `MatGetValues()` uses 0-based row and column numbers in 2066 Fortran as well as in C. 2067 2068 `MatGetValues()` requires that the matrix has been assembled 2069 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2070 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2071 without intermediate matrix assembly. 2072 2073 Negative row or column indices will be ignored and those locations in `v` will be 2074 left unchanged. 2075 2076 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2077 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2078 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2079 2080 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2081 @*/ 2082 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2083 { 2084 PetscFunctionBegin; 2085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2086 PetscValidType(mat, 1); 2087 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2088 PetscAssertPointer(idxm, 3); 2089 PetscAssertPointer(idxn, 5); 2090 PetscAssertPointer(v, 6); 2091 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2092 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2093 MatCheckPreallocated(mat, 1); 2094 2095 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2096 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2097 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2098 PetscFunctionReturn(PETSC_SUCCESS); 2099 } 2100 2101 /*@C 2102 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2103 defined previously by `MatSetLocalToGlobalMapping()` 2104 2105 Not Collective 2106 2107 Input Parameters: 2108 + mat - the matrix 2109 . nrow - number of rows 2110 . irow - the row local indices 2111 . ncol - number of columns 2112 - icol - the column local indices 2113 2114 Output Parameter: 2115 . y - a logically two-dimensional array of values 2116 2117 Level: advanced 2118 2119 Notes: 2120 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2121 2122 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, 2123 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2124 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2125 with `MatSetLocalToGlobalMapping()`. 2126 2127 Developer Note: 2128 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2129 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2130 2131 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2132 `MatSetValuesLocal()`, `MatGetValues()` 2133 @*/ 2134 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2135 { 2136 PetscFunctionBeginHot; 2137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2138 PetscValidType(mat, 1); 2139 MatCheckPreallocated(mat, 1); 2140 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2141 PetscAssertPointer(irow, 3); 2142 PetscAssertPointer(icol, 5); 2143 if (PetscDefined(USE_DEBUG)) { 2144 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2145 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2146 } 2147 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2148 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2149 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2150 else { 2151 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2152 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2153 irowm = buf; 2154 icolm = buf + nrow; 2155 } else { 2156 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2157 irowm = bufr; 2158 icolm = bufc; 2159 } 2160 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2161 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2162 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2163 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2164 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2165 PetscCall(PetscFree2(bufr, bufc)); 2166 } 2167 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2168 PetscFunctionReturn(PETSC_SUCCESS); 2169 } 2170 2171 /*@ 2172 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2173 the same size. Currently, this can only be called once and creates the given matrix. 2174 2175 Not Collective 2176 2177 Input Parameters: 2178 + mat - the matrix 2179 . nb - the number of blocks 2180 . bs - the number of rows (and columns) in each block 2181 . rows - a concatenation of the rows for each block 2182 - v - a concatenation of logically two-dimensional arrays of values 2183 2184 Level: advanced 2185 2186 Notes: 2187 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2188 2189 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2190 2191 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2192 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2193 @*/ 2194 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2195 { 2196 PetscFunctionBegin; 2197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2198 PetscValidType(mat, 1); 2199 PetscAssertPointer(rows, 4); 2200 PetscAssertPointer(v, 5); 2201 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2202 2203 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2204 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2205 else { 2206 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2207 } 2208 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2209 PetscFunctionReturn(PETSC_SUCCESS); 2210 } 2211 2212 /*@ 2213 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2214 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2215 using a local (per-processor) numbering. 2216 2217 Not Collective 2218 2219 Input Parameters: 2220 + x - the matrix 2221 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2222 - cmapping - column mapping 2223 2224 Level: intermediate 2225 2226 Note: 2227 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2228 2229 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2230 @*/ 2231 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2232 { 2233 PetscFunctionBegin; 2234 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2235 PetscValidType(x, 1); 2236 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2237 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2238 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2239 else { 2240 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2241 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2242 } 2243 PetscFunctionReturn(PETSC_SUCCESS); 2244 } 2245 2246 /*@ 2247 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2248 2249 Not Collective 2250 2251 Input Parameter: 2252 . A - the matrix 2253 2254 Output Parameters: 2255 + rmapping - row mapping 2256 - cmapping - column mapping 2257 2258 Level: advanced 2259 2260 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2261 @*/ 2262 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2263 { 2264 PetscFunctionBegin; 2265 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2266 PetscValidType(A, 1); 2267 if (rmapping) { 2268 PetscAssertPointer(rmapping, 2); 2269 *rmapping = A->rmap->mapping; 2270 } 2271 if (cmapping) { 2272 PetscAssertPointer(cmapping, 3); 2273 *cmapping = A->cmap->mapping; 2274 } 2275 PetscFunctionReturn(PETSC_SUCCESS); 2276 } 2277 2278 /*@ 2279 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2280 2281 Logically Collective 2282 2283 Input Parameters: 2284 + A - the matrix 2285 . rmap - row layout 2286 - cmap - column layout 2287 2288 Level: advanced 2289 2290 Note: 2291 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2292 2293 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2294 @*/ 2295 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2296 { 2297 PetscFunctionBegin; 2298 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2299 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2300 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2301 PetscFunctionReturn(PETSC_SUCCESS); 2302 } 2303 2304 /*@ 2305 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2306 2307 Not Collective 2308 2309 Input Parameter: 2310 . A - the matrix 2311 2312 Output Parameters: 2313 + rmap - row layout 2314 - cmap - column layout 2315 2316 Level: advanced 2317 2318 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2319 @*/ 2320 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2321 { 2322 PetscFunctionBegin; 2323 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2324 PetscValidType(A, 1); 2325 if (rmap) { 2326 PetscAssertPointer(rmap, 2); 2327 *rmap = A->rmap; 2328 } 2329 if (cmap) { 2330 PetscAssertPointer(cmap, 3); 2331 *cmap = A->cmap; 2332 } 2333 PetscFunctionReturn(PETSC_SUCCESS); 2334 } 2335 2336 /*@C 2337 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2338 using a local numbering of the rows and columns. 2339 2340 Not Collective 2341 2342 Input Parameters: 2343 + mat - the matrix 2344 . nrow - number of rows 2345 . irow - the row local indices 2346 . ncol - number of columns 2347 . icol - the column local indices 2348 . y - a logically two-dimensional array of values 2349 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2350 2351 Level: intermediate 2352 2353 Notes: 2354 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2355 2356 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2357 options cannot be mixed without intervening calls to the assembly 2358 routines. 2359 2360 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2361 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2362 2363 Developer Note: 2364 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2365 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2366 2367 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2368 `MatGetValuesLocal()` 2369 @*/ 2370 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2371 { 2372 PetscFunctionBeginHot; 2373 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2374 PetscValidType(mat, 1); 2375 MatCheckPreallocated(mat, 1); 2376 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2377 PetscAssertPointer(irow, 3); 2378 PetscAssertPointer(icol, 5); 2379 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2380 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2381 if (PetscDefined(USE_DEBUG)) { 2382 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2383 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2384 } 2385 2386 if (mat->assembled) { 2387 mat->was_assembled = PETSC_TRUE; 2388 mat->assembled = PETSC_FALSE; 2389 } 2390 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2391 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2392 else { 2393 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2394 const PetscInt *irowm, *icolm; 2395 2396 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2397 bufr = buf; 2398 bufc = buf + nrow; 2399 irowm = bufr; 2400 icolm = bufc; 2401 } else { 2402 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2403 irowm = bufr; 2404 icolm = bufc; 2405 } 2406 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2407 else irowm = irow; 2408 if (mat->cmap->mapping) { 2409 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2410 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2411 } else icolm = irowm; 2412 } else icolm = icol; 2413 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2414 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2415 } 2416 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2417 PetscFunctionReturn(PETSC_SUCCESS); 2418 } 2419 2420 /*@C 2421 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2422 using a local ordering of the nodes a block at a time. 2423 2424 Not Collective 2425 2426 Input Parameters: 2427 + mat - the matrix 2428 . nrow - number of rows 2429 . irow - the row local indices 2430 . ncol - number of columns 2431 . icol - the column local indices 2432 . y - a logically two-dimensional array of values 2433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2434 2435 Level: intermediate 2436 2437 Notes: 2438 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2439 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2440 2441 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2442 options cannot be mixed without intervening calls to the assembly 2443 routines. 2444 2445 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2446 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2447 2448 Developer Note: 2449 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2450 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2451 2452 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2453 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2454 @*/ 2455 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2456 { 2457 PetscFunctionBeginHot; 2458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2459 PetscValidType(mat, 1); 2460 MatCheckPreallocated(mat, 1); 2461 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2462 PetscAssertPointer(irow, 3); 2463 PetscAssertPointer(icol, 5); 2464 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2465 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2466 if (PetscDefined(USE_DEBUG)) { 2467 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2468 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); 2469 } 2470 2471 if (mat->assembled) { 2472 mat->was_assembled = PETSC_TRUE; 2473 mat->assembled = PETSC_FALSE; 2474 } 2475 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2476 PetscInt irbs, rbs; 2477 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2478 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2479 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2480 } 2481 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2482 PetscInt icbs, cbs; 2483 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2484 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2485 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2486 } 2487 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2488 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2489 else { 2490 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2491 const PetscInt *irowm, *icolm; 2492 2493 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2494 bufr = buf; 2495 bufc = buf + nrow; 2496 irowm = bufr; 2497 icolm = bufc; 2498 } else { 2499 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2500 irowm = bufr; 2501 icolm = bufc; 2502 } 2503 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2504 else irowm = irow; 2505 if (mat->cmap->mapping) { 2506 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2507 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2508 } else icolm = irowm; 2509 } else icolm = icol; 2510 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2511 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2512 } 2513 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2514 PetscFunctionReturn(PETSC_SUCCESS); 2515 } 2516 2517 /*@ 2518 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2519 2520 Collective 2521 2522 Input Parameters: 2523 + mat - the matrix 2524 - x - the vector to be multiplied 2525 2526 Output Parameter: 2527 . y - the result 2528 2529 Level: developer 2530 2531 Note: 2532 The vectors `x` and `y` cannot be the same. I.e., one cannot 2533 call `MatMultDiagonalBlock`(A,y,y). 2534 2535 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2536 @*/ 2537 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2538 { 2539 PetscFunctionBegin; 2540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2541 PetscValidType(mat, 1); 2542 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2543 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2544 2545 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2546 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2547 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2548 MatCheckPreallocated(mat, 1); 2549 2550 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2551 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2552 PetscFunctionReturn(PETSC_SUCCESS); 2553 } 2554 2555 /*@ 2556 MatMult - Computes the matrix-vector product, $y = Ax$. 2557 2558 Neighbor-wise Collective 2559 2560 Input Parameters: 2561 + mat - the matrix 2562 - x - the vector to be multiplied 2563 2564 Output Parameter: 2565 . y - the result 2566 2567 Level: beginner 2568 2569 Note: 2570 The vectors `x` and `y` cannot be the same. I.e., one cannot 2571 call `MatMult`(A,y,y). 2572 2573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2574 @*/ 2575 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2576 { 2577 PetscFunctionBegin; 2578 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2579 PetscValidType(mat, 1); 2580 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2581 VecCheckAssembled(x); 2582 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2583 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2584 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2585 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2586 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); 2587 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); 2588 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); 2589 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); 2590 PetscCall(VecSetErrorIfLocked(y, 3)); 2591 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2592 MatCheckPreallocated(mat, 1); 2593 2594 PetscCall(VecLockReadPush(x)); 2595 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2596 PetscUseTypeMethod(mat, mult, x, y); 2597 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2598 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2599 PetscCall(VecLockReadPop(x)); 2600 PetscFunctionReturn(PETSC_SUCCESS); 2601 } 2602 2603 /*@ 2604 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2605 2606 Neighbor-wise Collective 2607 2608 Input Parameters: 2609 + mat - the matrix 2610 - x - the vector to be multiplied 2611 2612 Output Parameter: 2613 . y - the result 2614 2615 Level: beginner 2616 2617 Notes: 2618 The vectors `x` and `y` cannot be the same. I.e., one cannot 2619 call `MatMultTranspose`(A,y,y). 2620 2621 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2622 use `MatMultHermitianTranspose()` 2623 2624 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2625 @*/ 2626 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2627 { 2628 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2629 2630 PetscFunctionBegin; 2631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2632 PetscValidType(mat, 1); 2633 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2634 VecCheckAssembled(x); 2635 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2636 2637 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2638 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2639 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2640 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); 2641 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); 2642 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); 2643 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); 2644 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2645 MatCheckPreallocated(mat, 1); 2646 2647 if (!mat->ops->multtranspose) { 2648 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2649 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); 2650 } else op = mat->ops->multtranspose; 2651 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2652 PetscCall(VecLockReadPush(x)); 2653 PetscCall((*op)(mat, x, y)); 2654 PetscCall(VecLockReadPop(x)); 2655 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2656 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2657 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2658 PetscFunctionReturn(PETSC_SUCCESS); 2659 } 2660 2661 /*@ 2662 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2663 2664 Neighbor-wise Collective 2665 2666 Input Parameters: 2667 + mat - the matrix 2668 - x - the vector to be multiplied 2669 2670 Output Parameter: 2671 . y - the result 2672 2673 Level: beginner 2674 2675 Notes: 2676 The vectors `x` and `y` cannot be the same. I.e., one cannot 2677 call `MatMultHermitianTranspose`(A,y,y). 2678 2679 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2680 2681 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2682 2683 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2684 @*/ 2685 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2686 { 2687 PetscFunctionBegin; 2688 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2689 PetscValidType(mat, 1); 2690 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2691 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2692 2693 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2694 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2695 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2696 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); 2697 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); 2698 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); 2699 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); 2700 MatCheckPreallocated(mat, 1); 2701 2702 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2703 #if defined(PETSC_USE_COMPLEX) 2704 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2705 PetscCall(VecLockReadPush(x)); 2706 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2707 else PetscUseTypeMethod(mat, mult, x, y); 2708 PetscCall(VecLockReadPop(x)); 2709 } else { 2710 Vec w; 2711 PetscCall(VecDuplicate(x, &w)); 2712 PetscCall(VecCopy(x, w)); 2713 PetscCall(VecConjugate(w)); 2714 PetscCall(MatMultTranspose(mat, w, y)); 2715 PetscCall(VecDestroy(&w)); 2716 PetscCall(VecConjugate(y)); 2717 } 2718 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2719 #else 2720 PetscCall(MatMultTranspose(mat, x, y)); 2721 #endif 2722 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2723 PetscFunctionReturn(PETSC_SUCCESS); 2724 } 2725 2726 /*@ 2727 MatMultAdd - Computes $v3 = v2 + A * v1$. 2728 2729 Neighbor-wise Collective 2730 2731 Input Parameters: 2732 + mat - the matrix 2733 . v1 - the vector to be multiplied by `mat` 2734 - v2 - the vector to be added to the result 2735 2736 Output Parameter: 2737 . v3 - the result 2738 2739 Level: beginner 2740 2741 Note: 2742 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2743 call `MatMultAdd`(A,v1,v2,v1). 2744 2745 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2746 @*/ 2747 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2748 { 2749 PetscFunctionBegin; 2750 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2751 PetscValidType(mat, 1); 2752 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2753 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2754 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2755 2756 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2757 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2758 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); 2759 /* 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); 2760 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); */ 2761 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); 2762 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); 2763 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2764 MatCheckPreallocated(mat, 1); 2765 2766 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2767 PetscCall(VecLockReadPush(v1)); 2768 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2769 PetscCall(VecLockReadPop(v1)); 2770 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2771 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2772 PetscFunctionReturn(PETSC_SUCCESS); 2773 } 2774 2775 /*@ 2776 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2777 2778 Neighbor-wise Collective 2779 2780 Input Parameters: 2781 + mat - the matrix 2782 . v1 - the vector to be multiplied by the transpose of the matrix 2783 - v2 - the vector to be added to the result 2784 2785 Output Parameter: 2786 . v3 - the result 2787 2788 Level: beginner 2789 2790 Note: 2791 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2792 call `MatMultTransposeAdd`(A,v1,v2,v1). 2793 2794 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2795 @*/ 2796 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2797 { 2798 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2799 2800 PetscFunctionBegin; 2801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2802 PetscValidType(mat, 1); 2803 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2804 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2805 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2806 2807 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2808 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2809 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); 2810 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); 2811 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); 2812 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2813 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2814 MatCheckPreallocated(mat, 1); 2815 2816 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2817 PetscCall(VecLockReadPush(v1)); 2818 PetscCall((*op)(mat, v1, v2, v3)); 2819 PetscCall(VecLockReadPop(v1)); 2820 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2821 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2822 PetscFunctionReturn(PETSC_SUCCESS); 2823 } 2824 2825 /*@ 2826 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2827 2828 Neighbor-wise Collective 2829 2830 Input Parameters: 2831 + mat - the matrix 2832 . v1 - the vector to be multiplied by the Hermitian transpose 2833 - v2 - the vector to be added to the result 2834 2835 Output Parameter: 2836 . v3 - the result 2837 2838 Level: beginner 2839 2840 Note: 2841 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2842 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2843 2844 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2845 @*/ 2846 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2847 { 2848 PetscFunctionBegin; 2849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2850 PetscValidType(mat, 1); 2851 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2852 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2853 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2854 2855 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2856 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2857 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2858 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); 2859 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); 2860 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); 2861 MatCheckPreallocated(mat, 1); 2862 2863 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2864 PetscCall(VecLockReadPush(v1)); 2865 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2866 else { 2867 Vec w, z; 2868 PetscCall(VecDuplicate(v1, &w)); 2869 PetscCall(VecCopy(v1, w)); 2870 PetscCall(VecConjugate(w)); 2871 PetscCall(VecDuplicate(v3, &z)); 2872 PetscCall(MatMultTranspose(mat, w, z)); 2873 PetscCall(VecDestroy(&w)); 2874 PetscCall(VecConjugate(z)); 2875 if (v2 != v3) { 2876 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2877 } else { 2878 PetscCall(VecAXPY(v3, 1.0, z)); 2879 } 2880 PetscCall(VecDestroy(&z)); 2881 } 2882 PetscCall(VecLockReadPop(v1)); 2883 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2884 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2885 PetscFunctionReturn(PETSC_SUCCESS); 2886 } 2887 2888 /*@C 2889 MatGetFactorType - gets the type of factorization a matrix is 2890 2891 Not Collective 2892 2893 Input Parameter: 2894 . mat - the matrix 2895 2896 Output Parameter: 2897 . 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` 2898 2899 Level: intermediate 2900 2901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2902 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2903 @*/ 2904 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 PetscAssertPointer(t, 2); 2910 *t = mat->factortype; 2911 PetscFunctionReturn(PETSC_SUCCESS); 2912 } 2913 2914 /*@C 2915 MatSetFactorType - sets the type of factorization a matrix is 2916 2917 Logically Collective 2918 2919 Input Parameters: 2920 + mat - the matrix 2921 - 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` 2922 2923 Level: intermediate 2924 2925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2926 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2927 @*/ 2928 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2929 { 2930 PetscFunctionBegin; 2931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2932 PetscValidType(mat, 1); 2933 mat->factortype = t; 2934 PetscFunctionReturn(PETSC_SUCCESS); 2935 } 2936 2937 /*@C 2938 MatGetInfo - Returns information about matrix storage (number of 2939 nonzeros, memory, etc.). 2940 2941 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2942 2943 Input Parameters: 2944 + mat - the matrix 2945 - 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) 2946 2947 Output Parameter: 2948 . info - matrix information context 2949 2950 Options Database Key: 2951 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2952 2953 Notes: 2954 The `MatInfo` context contains a variety of matrix data, including 2955 number of nonzeros allocated and used, number of mallocs during 2956 matrix assembly, etc. Additional information for factored matrices 2957 is provided (such as the fill ratio, number of mallocs during 2958 factorization, etc.). 2959 2960 Example: 2961 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2962 data within the MatInfo context. For example, 2963 .vb 2964 MatInfo info; 2965 Mat A; 2966 double mal, nz_a, nz_u; 2967 2968 MatGetInfo(A, MAT_LOCAL, &info); 2969 mal = info.mallocs; 2970 nz_a = info.nz_allocated; 2971 .ve 2972 2973 Fortran users should declare info as a double precision 2974 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2975 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2976 a complete list of parameter names. 2977 .vb 2978 double precision info(MAT_INFO_SIZE) 2979 double precision mal, nz_a 2980 Mat A 2981 integer ierr 2982 2983 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2984 mal = info(MAT_INFO_MALLOCS) 2985 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2986 .ve 2987 2988 Level: intermediate 2989 2990 Developer Note: 2991 The Fortran interface is not autogenerated as the 2992 interface definition cannot be generated correctly [due to `MatInfo` argument] 2993 2994 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2995 @*/ 2996 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2997 { 2998 PetscFunctionBegin; 2999 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3000 PetscValidType(mat, 1); 3001 PetscAssertPointer(info, 3); 3002 MatCheckPreallocated(mat, 1); 3003 PetscUseTypeMethod(mat, getinfo, flag, info); 3004 PetscFunctionReturn(PETSC_SUCCESS); 3005 } 3006 3007 /* 3008 This is used by external packages where it is not easy to get the info from the actual 3009 matrix factorization. 3010 */ 3011 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3012 { 3013 PetscFunctionBegin; 3014 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3015 PetscFunctionReturn(PETSC_SUCCESS); 3016 } 3017 3018 /*@C 3019 MatLUFactor - Performs in-place LU factorization of matrix. 3020 3021 Collective 3022 3023 Input Parameters: 3024 + mat - the matrix 3025 . row - row permutation 3026 . col - column permutation 3027 - info - options for factorization, includes 3028 .vb 3029 fill - expected fill as ratio of original fill. 3030 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3031 Run with the option -info to determine an optimal value to use 3032 .ve 3033 3034 Level: developer 3035 3036 Notes: 3037 Most users should employ the `KSP` interface for linear solvers 3038 instead of working directly with matrix algebra routines such as this. 3039 See, e.g., `KSPCreate()`. 3040 3041 This changes the state of the matrix to a factored matrix; it cannot be used 3042 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3043 3044 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3045 when not using `KSP`. 3046 3047 Developer Note: 3048 The Fortran interface is not autogenerated as the 3049 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3050 3051 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3052 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3053 @*/ 3054 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3055 { 3056 MatFactorInfo tinfo; 3057 3058 PetscFunctionBegin; 3059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3060 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3061 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3062 if (info) PetscAssertPointer(info, 4); 3063 PetscValidType(mat, 1); 3064 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3065 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3066 MatCheckPreallocated(mat, 1); 3067 if (!info) { 3068 PetscCall(MatFactorInfoInitialize(&tinfo)); 3069 info = &tinfo; 3070 } 3071 3072 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3073 PetscUseTypeMethod(mat, lufactor, row, col, info); 3074 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3075 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3076 PetscFunctionReturn(PETSC_SUCCESS); 3077 } 3078 3079 /*@C 3080 MatILUFactor - Performs in-place ILU factorization of matrix. 3081 3082 Collective 3083 3084 Input Parameters: 3085 + mat - the matrix 3086 . row - row permutation 3087 . col - column permutation 3088 - info - structure containing 3089 .vb 3090 levels - number of levels of fill. 3091 expected fill - as ratio of original fill. 3092 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3093 missing diagonal entries) 3094 .ve 3095 3096 Level: developer 3097 3098 Notes: 3099 Most users should employ the `KSP` interface for linear solvers 3100 instead of working directly with matrix algebra routines such as this. 3101 See, e.g., `KSPCreate()`. 3102 3103 Probably really in-place only when level of fill is zero, otherwise allocates 3104 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3105 when not using `KSP`. 3106 3107 Developer Note: 3108 The Fortran interface is not autogenerated as the 3109 interface definition cannot be generated correctly [due to MatFactorInfo] 3110 3111 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3112 @*/ 3113 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3114 { 3115 PetscFunctionBegin; 3116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3117 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3118 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3119 PetscAssertPointer(info, 4); 3120 PetscValidType(mat, 1); 3121 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3122 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3123 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3124 MatCheckPreallocated(mat, 1); 3125 3126 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3127 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3128 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3129 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3130 PetscFunctionReturn(PETSC_SUCCESS); 3131 } 3132 3133 /*@C 3134 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3135 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3136 3137 Collective 3138 3139 Input Parameters: 3140 + fact - the factor matrix obtained with `MatGetFactor()` 3141 . mat - the matrix 3142 . row - the row permutation 3143 . col - the column permutation 3144 - info - options for factorization, includes 3145 .vb 3146 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3147 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3148 .ve 3149 3150 Level: developer 3151 3152 Notes: 3153 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3154 3155 Most users should employ the simplified `KSP` interface for linear solvers 3156 instead of working directly with matrix algebra routines such as this. 3157 See, e.g., `KSPCreate()`. 3158 3159 Developer Note: 3160 The Fortran interface is not autogenerated as the 3161 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3162 3163 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3164 @*/ 3165 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3166 { 3167 MatFactorInfo tinfo; 3168 3169 PetscFunctionBegin; 3170 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3171 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3172 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3173 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3174 if (info) PetscAssertPointer(info, 5); 3175 PetscValidType(fact, 1); 3176 PetscValidType(mat, 2); 3177 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3178 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3179 MatCheckPreallocated(mat, 2); 3180 if (!info) { 3181 PetscCall(MatFactorInfoInitialize(&tinfo)); 3182 info = &tinfo; 3183 } 3184 3185 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3186 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3187 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3188 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3189 PetscFunctionReturn(PETSC_SUCCESS); 3190 } 3191 3192 /*@C 3193 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3194 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3195 3196 Collective 3197 3198 Input Parameters: 3199 + fact - the factor matrix obtained with `MatGetFactor()` 3200 . mat - the matrix 3201 - info - options for factorization 3202 3203 Level: developer 3204 3205 Notes: 3206 See `MatLUFactor()` for in-place factorization. See 3207 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3208 3209 Most users should employ the `KSP` interface for linear solvers 3210 instead of working directly with matrix algebra routines such as this. 3211 See, e.g., `KSPCreate()`. 3212 3213 Developer Note: 3214 The Fortran interface is not autogenerated as the 3215 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3216 3217 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3218 @*/ 3219 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3220 { 3221 MatFactorInfo tinfo; 3222 3223 PetscFunctionBegin; 3224 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3226 PetscValidType(fact, 1); 3227 PetscValidType(mat, 2); 3228 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3229 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, 3230 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3231 3232 MatCheckPreallocated(mat, 2); 3233 if (!info) { 3234 PetscCall(MatFactorInfoInitialize(&tinfo)); 3235 info = &tinfo; 3236 } 3237 3238 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3239 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3240 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3241 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3242 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3243 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3244 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3245 PetscFunctionReturn(PETSC_SUCCESS); 3246 } 3247 3248 /*@C 3249 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3250 symmetric matrix. 3251 3252 Collective 3253 3254 Input Parameters: 3255 + mat - the matrix 3256 . perm - row and column permutations 3257 - info - expected fill as ratio of original fill 3258 3259 Level: developer 3260 3261 Notes: 3262 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3263 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3264 3265 Most users should employ the `KSP` interface for linear solvers 3266 instead of working directly with matrix algebra routines such as this. 3267 See, e.g., `KSPCreate()`. 3268 3269 Developer Note: 3270 The Fortran interface is not autogenerated as the 3271 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3272 3273 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3274 `MatGetOrdering()` 3275 @*/ 3276 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3277 { 3278 MatFactorInfo tinfo; 3279 3280 PetscFunctionBegin; 3281 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3282 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3283 if (info) PetscAssertPointer(info, 3); 3284 PetscValidType(mat, 1); 3285 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3286 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3287 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3288 MatCheckPreallocated(mat, 1); 3289 if (!info) { 3290 PetscCall(MatFactorInfoInitialize(&tinfo)); 3291 info = &tinfo; 3292 } 3293 3294 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3295 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3296 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3297 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3298 PetscFunctionReturn(PETSC_SUCCESS); 3299 } 3300 3301 /*@C 3302 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3303 of a symmetric matrix. 3304 3305 Collective 3306 3307 Input Parameters: 3308 + fact - the factor matrix obtained with `MatGetFactor()` 3309 . mat - the matrix 3310 . perm - row and column permutations 3311 - info - options for factorization, includes 3312 .vb 3313 fill - expected fill as ratio of original fill. 3314 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3315 Run with the option -info to determine an optimal value to use 3316 .ve 3317 3318 Level: developer 3319 3320 Notes: 3321 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3322 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3323 3324 Most users should employ the `KSP` interface for linear solvers 3325 instead of working directly with matrix algebra routines such as this. 3326 See, e.g., `KSPCreate()`. 3327 3328 Developer Note: 3329 The Fortran interface is not autogenerated as the 3330 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3331 3332 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3333 `MatGetOrdering()` 3334 @*/ 3335 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3336 { 3337 MatFactorInfo tinfo; 3338 3339 PetscFunctionBegin; 3340 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3341 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3342 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3343 if (info) PetscAssertPointer(info, 4); 3344 PetscValidType(fact, 1); 3345 PetscValidType(mat, 2); 3346 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3347 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3348 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3349 MatCheckPreallocated(mat, 2); 3350 if (!info) { 3351 PetscCall(MatFactorInfoInitialize(&tinfo)); 3352 info = &tinfo; 3353 } 3354 3355 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3356 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3357 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3358 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3359 PetscFunctionReturn(PETSC_SUCCESS); 3360 } 3361 3362 /*@C 3363 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3364 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3365 `MatCholeskyFactorSymbolic()`. 3366 3367 Collective 3368 3369 Input Parameters: 3370 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3371 . mat - the initial matrix that is to be factored 3372 - info - options for factorization 3373 3374 Level: developer 3375 3376 Note: 3377 Most users should employ the `KSP` interface for linear solvers 3378 instead of working directly with matrix algebra routines such as this. 3379 See, e.g., `KSPCreate()`. 3380 3381 Developer Note: 3382 The Fortran interface is not autogenerated as the 3383 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3384 3385 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3386 @*/ 3387 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3388 { 3389 MatFactorInfo tinfo; 3390 3391 PetscFunctionBegin; 3392 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3394 PetscValidType(fact, 1); 3395 PetscValidType(mat, 2); 3396 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3397 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, 3398 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3399 MatCheckPreallocated(mat, 2); 3400 if (!info) { 3401 PetscCall(MatFactorInfoInitialize(&tinfo)); 3402 info = &tinfo; 3403 } 3404 3405 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3406 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3407 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3408 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3409 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3410 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3411 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3412 PetscFunctionReturn(PETSC_SUCCESS); 3413 } 3414 3415 /*@ 3416 MatQRFactor - Performs in-place QR factorization of matrix. 3417 3418 Collective 3419 3420 Input Parameters: 3421 + mat - the matrix 3422 . col - column permutation 3423 - info - options for factorization, includes 3424 .vb 3425 fill - expected fill as ratio of original fill. 3426 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3427 Run with the option -info to determine an optimal value to use 3428 .ve 3429 3430 Level: developer 3431 3432 Notes: 3433 Most users should employ the `KSP` interface for linear solvers 3434 instead of working directly with matrix algebra routines such as this. 3435 See, e.g., `KSPCreate()`. 3436 3437 This changes the state of the matrix to a factored matrix; it cannot be used 3438 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3439 3440 Developer Note: 3441 The Fortran interface is not autogenerated as the 3442 interface definition cannot be generated correctly [due to MatFactorInfo] 3443 3444 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3445 `MatSetUnfactored()` 3446 @*/ 3447 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3448 { 3449 PetscFunctionBegin; 3450 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3451 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3452 if (info) PetscAssertPointer(info, 3); 3453 PetscValidType(mat, 1); 3454 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3455 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3456 MatCheckPreallocated(mat, 1); 3457 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3458 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3459 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3460 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3461 PetscFunctionReturn(PETSC_SUCCESS); 3462 } 3463 3464 /*@ 3465 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3466 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3467 3468 Collective 3469 3470 Input Parameters: 3471 + fact - the factor matrix obtained with `MatGetFactor()` 3472 . mat - the matrix 3473 . col - column permutation 3474 - info - options for factorization, includes 3475 .vb 3476 fill - expected fill as ratio of original fill. 3477 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3478 Run with the option -info to determine an optimal value to use 3479 .ve 3480 3481 Level: developer 3482 3483 Note: 3484 Most users should employ the `KSP` interface for linear solvers 3485 instead of working directly with matrix algebra routines such as this. 3486 See, e.g., `KSPCreate()`. 3487 3488 Developer Note: 3489 The Fortran interface is not autogenerated as the 3490 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3491 3492 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3493 @*/ 3494 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3495 { 3496 MatFactorInfo tinfo; 3497 3498 PetscFunctionBegin; 3499 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3500 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3501 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3502 if (info) PetscAssertPointer(info, 4); 3503 PetscValidType(fact, 1); 3504 PetscValidType(mat, 2); 3505 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3506 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3507 MatCheckPreallocated(mat, 2); 3508 if (!info) { 3509 PetscCall(MatFactorInfoInitialize(&tinfo)); 3510 info = &tinfo; 3511 } 3512 3513 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3514 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3515 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3516 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3517 PetscFunctionReturn(PETSC_SUCCESS); 3518 } 3519 3520 /*@ 3521 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3522 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3523 3524 Collective 3525 3526 Input Parameters: 3527 + fact - the factor matrix obtained with `MatGetFactor()` 3528 . mat - the matrix 3529 - info - options for factorization 3530 3531 Level: developer 3532 3533 Notes: 3534 See `MatQRFactor()` for in-place factorization. 3535 3536 Most users should employ the `KSP` interface for linear solvers 3537 instead of working directly with matrix algebra routines such as this. 3538 See, e.g., `KSPCreate()`. 3539 3540 Developer Note: 3541 The Fortran interface is not autogenerated as the 3542 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3543 3544 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3545 @*/ 3546 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3547 { 3548 MatFactorInfo tinfo; 3549 3550 PetscFunctionBegin; 3551 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3553 PetscValidType(fact, 1); 3554 PetscValidType(mat, 2); 3555 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3556 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, 3557 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3558 3559 MatCheckPreallocated(mat, 2); 3560 if (!info) { 3561 PetscCall(MatFactorInfoInitialize(&tinfo)); 3562 info = &tinfo; 3563 } 3564 3565 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3566 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3567 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3568 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3569 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3570 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3571 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3572 PetscFunctionReturn(PETSC_SUCCESS); 3573 } 3574 3575 /*@ 3576 MatSolve - Solves $A x = b$, given a factored matrix. 3577 3578 Neighbor-wise Collective 3579 3580 Input Parameters: 3581 + mat - the factored matrix 3582 - b - the right-hand-side vector 3583 3584 Output Parameter: 3585 . x - the result vector 3586 3587 Level: developer 3588 3589 Notes: 3590 The vectors `b` and `x` cannot be the same. I.e., one cannot 3591 call `MatSolve`(A,x,x). 3592 3593 Most users should employ the `KSP` interface for linear solvers 3594 instead of working directly with matrix algebra routines such as this. 3595 See, e.g., `KSPCreate()`. 3596 3597 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3598 @*/ 3599 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3600 { 3601 PetscFunctionBegin; 3602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3603 PetscValidType(mat, 1); 3604 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3605 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3606 PetscCheckSameComm(mat, 1, b, 2); 3607 PetscCheckSameComm(mat, 1, x, 3); 3608 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3609 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); 3610 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); 3611 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); 3612 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3613 MatCheckPreallocated(mat, 1); 3614 3615 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3616 if (mat->factorerrortype) { 3617 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3618 PetscCall(VecSetInf(x)); 3619 } else PetscUseTypeMethod(mat, solve, b, x); 3620 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3621 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3622 PetscFunctionReturn(PETSC_SUCCESS); 3623 } 3624 3625 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3626 { 3627 Vec b, x; 3628 PetscInt N, i; 3629 PetscErrorCode (*f)(Mat, Vec, Vec); 3630 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3631 3632 PetscFunctionBegin; 3633 if (A->factorerrortype) { 3634 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3635 PetscCall(MatSetInf(X)); 3636 PetscFunctionReturn(PETSC_SUCCESS); 3637 } 3638 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3639 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3640 PetscCall(MatBoundToCPU(A, &Abound)); 3641 if (!Abound) { 3642 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3643 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3644 } 3645 #if PetscDefined(HAVE_CUDA) 3646 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3647 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3648 #elif PetscDefined(HAVE_HIP) 3649 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3650 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3651 #endif 3652 PetscCall(MatGetSize(B, NULL, &N)); 3653 for (i = 0; i < N; i++) { 3654 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3655 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3656 PetscCall((*f)(A, b, x)); 3657 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3658 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3659 } 3660 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3661 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3662 PetscFunctionReturn(PETSC_SUCCESS); 3663 } 3664 3665 /*@ 3666 MatMatSolve - Solves $A X = B$, given a factored matrix. 3667 3668 Neighbor-wise Collective 3669 3670 Input Parameters: 3671 + A - the factored matrix 3672 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3673 3674 Output Parameter: 3675 . X - the result matrix (dense matrix) 3676 3677 Level: developer 3678 3679 Note: 3680 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3681 otherwise, `B` and `X` cannot be the same. 3682 3683 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3684 @*/ 3685 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3686 { 3687 PetscFunctionBegin; 3688 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3689 PetscValidType(A, 1); 3690 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3691 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3692 PetscCheckSameComm(A, 1, B, 2); 3693 PetscCheckSameComm(A, 1, X, 3); 3694 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); 3695 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); 3696 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"); 3697 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3698 MatCheckPreallocated(A, 1); 3699 3700 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3701 if (!A->ops->matsolve) { 3702 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3703 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3704 } else PetscUseTypeMethod(A, matsolve, B, X); 3705 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3706 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3707 PetscFunctionReturn(PETSC_SUCCESS); 3708 } 3709 3710 /*@ 3711 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3712 3713 Neighbor-wise Collective 3714 3715 Input Parameters: 3716 + A - the factored matrix 3717 - B - the right-hand-side matrix (`MATDENSE` matrix) 3718 3719 Output Parameter: 3720 . X - the result matrix (dense matrix) 3721 3722 Level: developer 3723 3724 Note: 3725 The matrices `B` and `X` cannot be the same. I.e., one cannot 3726 call `MatMatSolveTranspose`(A,X,X). 3727 3728 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3729 @*/ 3730 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3731 { 3732 PetscFunctionBegin; 3733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3734 PetscValidType(A, 1); 3735 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3736 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3737 PetscCheckSameComm(A, 1, B, 2); 3738 PetscCheckSameComm(A, 1, X, 3); 3739 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3740 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); 3741 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); 3742 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); 3743 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"); 3744 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3745 MatCheckPreallocated(A, 1); 3746 3747 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3748 if (!A->ops->matsolvetranspose) { 3749 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3750 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3751 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3752 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3753 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3754 PetscFunctionReturn(PETSC_SUCCESS); 3755 } 3756 3757 /*@ 3758 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3759 3760 Neighbor-wise Collective 3761 3762 Input Parameters: 3763 + A - the factored matrix 3764 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3765 3766 Output Parameter: 3767 . X - the result matrix (dense matrix) 3768 3769 Level: developer 3770 3771 Note: 3772 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 3773 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3774 3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3776 @*/ 3777 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3778 { 3779 PetscFunctionBegin; 3780 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3781 PetscValidType(A, 1); 3782 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3783 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3784 PetscCheckSameComm(A, 1, Bt, 2); 3785 PetscCheckSameComm(A, 1, X, 3); 3786 3787 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3788 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); 3789 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); 3790 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"); 3791 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3792 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3793 MatCheckPreallocated(A, 1); 3794 3795 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3796 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3797 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3798 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3799 PetscFunctionReturn(PETSC_SUCCESS); 3800 } 3801 3802 /*@ 3803 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3804 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3805 3806 Neighbor-wise Collective 3807 3808 Input Parameters: 3809 + mat - the factored matrix 3810 - b - the right-hand-side vector 3811 3812 Output Parameter: 3813 . x - the result vector 3814 3815 Level: developer 3816 3817 Notes: 3818 `MatSolve()` should be used for most applications, as it performs 3819 a forward solve followed by a backward solve. 3820 3821 The vectors `b` and `x` cannot be the same, i.e., one cannot 3822 call `MatForwardSolve`(A,x,x). 3823 3824 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3825 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3826 `MatForwardSolve()` solves $U^T*D y = b$, and 3827 `MatBackwardSolve()` solves $U x = y$. 3828 Thus they do not provide a symmetric preconditioner. 3829 3830 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3831 @*/ 3832 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3833 { 3834 PetscFunctionBegin; 3835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3836 PetscValidType(mat, 1); 3837 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3838 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3839 PetscCheckSameComm(mat, 1, b, 2); 3840 PetscCheckSameComm(mat, 1, x, 3); 3841 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3842 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); 3843 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); 3844 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); 3845 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3846 MatCheckPreallocated(mat, 1); 3847 3848 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3849 PetscUseTypeMethod(mat, forwardsolve, b, x); 3850 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3851 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3852 PetscFunctionReturn(PETSC_SUCCESS); 3853 } 3854 3855 /*@ 3856 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3857 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3858 3859 Neighbor-wise Collective 3860 3861 Input Parameters: 3862 + mat - the factored matrix 3863 - b - the right-hand-side vector 3864 3865 Output Parameter: 3866 . x - the result vector 3867 3868 Level: developer 3869 3870 Notes: 3871 `MatSolve()` should be used for most applications, as it performs 3872 a forward solve followed by a backward solve. 3873 3874 The vectors `b` and `x` cannot be the same. I.e., one cannot 3875 call `MatBackwardSolve`(A,x,x). 3876 3877 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3878 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3879 `MatForwardSolve()` solves $U^T*D y = b$, and 3880 `MatBackwardSolve()` solves $U x = y$. 3881 Thus they do not provide a symmetric preconditioner. 3882 3883 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3884 @*/ 3885 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3886 { 3887 PetscFunctionBegin; 3888 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3889 PetscValidType(mat, 1); 3890 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3891 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3892 PetscCheckSameComm(mat, 1, b, 2); 3893 PetscCheckSameComm(mat, 1, x, 3); 3894 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3895 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); 3896 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); 3897 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); 3898 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3899 MatCheckPreallocated(mat, 1); 3900 3901 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3902 PetscUseTypeMethod(mat, backwardsolve, b, x); 3903 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3904 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3905 PetscFunctionReturn(PETSC_SUCCESS); 3906 } 3907 3908 /*@ 3909 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3910 3911 Neighbor-wise Collective 3912 3913 Input Parameters: 3914 + mat - the factored matrix 3915 . b - the right-hand-side vector 3916 - y - the vector to be added to 3917 3918 Output Parameter: 3919 . x - the result vector 3920 3921 Level: developer 3922 3923 Note: 3924 The vectors `b` and `x` cannot be the same. I.e., one cannot 3925 call `MatSolveAdd`(A,x,y,x). 3926 3927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3928 @*/ 3929 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3930 { 3931 PetscScalar one = 1.0; 3932 Vec tmp; 3933 3934 PetscFunctionBegin; 3935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3936 PetscValidType(mat, 1); 3937 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3938 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3939 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3940 PetscCheckSameComm(mat, 1, b, 2); 3941 PetscCheckSameComm(mat, 1, y, 3); 3942 PetscCheckSameComm(mat, 1, x, 4); 3943 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3944 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); 3945 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); 3946 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); 3947 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); 3948 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); 3949 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3950 MatCheckPreallocated(mat, 1); 3951 3952 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3953 if (mat->factorerrortype) { 3954 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3955 PetscCall(VecSetInf(x)); 3956 } else if (mat->ops->solveadd) { 3957 PetscUseTypeMethod(mat, solveadd, b, y, x); 3958 } else { 3959 /* do the solve then the add manually */ 3960 if (x != y) { 3961 PetscCall(MatSolve(mat, b, x)); 3962 PetscCall(VecAXPY(x, one, y)); 3963 } else { 3964 PetscCall(VecDuplicate(x, &tmp)); 3965 PetscCall(VecCopy(x, tmp)); 3966 PetscCall(MatSolve(mat, b, x)); 3967 PetscCall(VecAXPY(x, one, tmp)); 3968 PetscCall(VecDestroy(&tmp)); 3969 } 3970 } 3971 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3972 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3973 PetscFunctionReturn(PETSC_SUCCESS); 3974 } 3975 3976 /*@ 3977 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 3978 3979 Neighbor-wise Collective 3980 3981 Input Parameters: 3982 + mat - the factored matrix 3983 - b - the right-hand-side vector 3984 3985 Output Parameter: 3986 . x - the result vector 3987 3988 Level: developer 3989 3990 Notes: 3991 The vectors `b` and `x` cannot be the same. I.e., one cannot 3992 call `MatSolveTranspose`(A,x,x). 3993 3994 Most users should employ the `KSP` interface for linear solvers 3995 instead of working directly with matrix algebra routines such as this. 3996 See, e.g., `KSPCreate()`. 3997 3998 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3999 @*/ 4000 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4001 { 4002 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4003 4004 PetscFunctionBegin; 4005 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4006 PetscValidType(mat, 1); 4007 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4008 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4009 PetscCheckSameComm(mat, 1, b, 2); 4010 PetscCheckSameComm(mat, 1, x, 3); 4011 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4012 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); 4013 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); 4014 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4015 MatCheckPreallocated(mat, 1); 4016 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4017 if (mat->factorerrortype) { 4018 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4019 PetscCall(VecSetInf(x)); 4020 } else { 4021 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4022 PetscCall((*f)(mat, b, x)); 4023 } 4024 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4025 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4026 PetscFunctionReturn(PETSC_SUCCESS); 4027 } 4028 4029 /*@ 4030 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4031 factored matrix. 4032 4033 Neighbor-wise Collective 4034 4035 Input Parameters: 4036 + mat - the factored matrix 4037 . b - the right-hand-side vector 4038 - y - the vector to be added to 4039 4040 Output Parameter: 4041 . x - the result vector 4042 4043 Level: developer 4044 4045 Note: 4046 The vectors `b` and `x` cannot be the same. I.e., one cannot 4047 call `MatSolveTransposeAdd`(A,x,y,x). 4048 4049 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4050 @*/ 4051 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4052 { 4053 PetscScalar one = 1.0; 4054 Vec tmp; 4055 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4056 4057 PetscFunctionBegin; 4058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4059 PetscValidType(mat, 1); 4060 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4061 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4062 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4063 PetscCheckSameComm(mat, 1, b, 2); 4064 PetscCheckSameComm(mat, 1, y, 3); 4065 PetscCheckSameComm(mat, 1, x, 4); 4066 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4067 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); 4068 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); 4069 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); 4070 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); 4071 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4072 MatCheckPreallocated(mat, 1); 4073 4074 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4075 if (mat->factorerrortype) { 4076 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4077 PetscCall(VecSetInf(x)); 4078 } else if (f) { 4079 PetscCall((*f)(mat, b, y, x)); 4080 } else { 4081 /* do the solve then the add manually */ 4082 if (x != y) { 4083 PetscCall(MatSolveTranspose(mat, b, x)); 4084 PetscCall(VecAXPY(x, one, y)); 4085 } else { 4086 PetscCall(VecDuplicate(x, &tmp)); 4087 PetscCall(VecCopy(x, tmp)); 4088 PetscCall(MatSolveTranspose(mat, b, x)); 4089 PetscCall(VecAXPY(x, one, tmp)); 4090 PetscCall(VecDestroy(&tmp)); 4091 } 4092 } 4093 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4094 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4095 PetscFunctionReturn(PETSC_SUCCESS); 4096 } 4097 4098 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4099 /*@ 4100 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4101 4102 Neighbor-wise Collective 4103 4104 Input Parameters: 4105 + mat - the matrix 4106 . b - the right hand side 4107 . omega - the relaxation factor 4108 . flag - flag indicating the type of SOR (see below) 4109 . shift - diagonal shift 4110 . its - the number of iterations 4111 - lits - the number of local iterations 4112 4113 Output Parameter: 4114 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4115 4116 SOR Flags: 4117 + `SOR_FORWARD_SWEEP` - forward SOR 4118 . `SOR_BACKWARD_SWEEP` - backward SOR 4119 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4120 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4121 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4122 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4123 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4124 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4125 upper/lower triangular part of matrix to 4126 vector (with omega) 4127 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4128 4129 Level: developer 4130 4131 Notes: 4132 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4133 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4134 on each processor. 4135 4136 Application programmers will not generally use `MatSOR()` directly, 4137 but instead will employ the `KSP`/`PC` interface. 4138 4139 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4140 4141 Most users should employ the `KSP` interface for linear solvers 4142 instead of working directly with matrix algebra routines such as this. 4143 See, e.g., `KSPCreate()`. 4144 4145 Vectors `x` and `b` CANNOT be the same 4146 4147 The flags are implemented as bitwise inclusive or operations. 4148 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4149 to specify a zero initial guess for SSOR. 4150 4151 Developer Note: 4152 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4153 4154 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4155 @*/ 4156 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4157 { 4158 PetscFunctionBegin; 4159 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4160 PetscValidType(mat, 1); 4161 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4162 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4163 PetscCheckSameComm(mat, 1, b, 2); 4164 PetscCheckSameComm(mat, 1, x, 8); 4165 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4166 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4167 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); 4168 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); 4169 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); 4170 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4171 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4172 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4173 4174 MatCheckPreallocated(mat, 1); 4175 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4176 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4177 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4178 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4179 PetscFunctionReturn(PETSC_SUCCESS); 4180 } 4181 4182 /* 4183 Default matrix copy routine. 4184 */ 4185 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4186 { 4187 PetscInt i, rstart = 0, rend = 0, nz; 4188 const PetscInt *cwork; 4189 const PetscScalar *vwork; 4190 4191 PetscFunctionBegin; 4192 if (B->assembled) PetscCall(MatZeroEntries(B)); 4193 if (str == SAME_NONZERO_PATTERN) { 4194 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4195 for (i = rstart; i < rend; i++) { 4196 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4197 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4198 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4199 } 4200 } else { 4201 PetscCall(MatAYPX(B, 0.0, A, str)); 4202 } 4203 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4204 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4205 PetscFunctionReturn(PETSC_SUCCESS); 4206 } 4207 4208 /*@ 4209 MatCopy - Copies a matrix to another matrix. 4210 4211 Collective 4212 4213 Input Parameters: 4214 + A - the matrix 4215 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4216 4217 Output Parameter: 4218 . B - where the copy is put 4219 4220 Level: intermediate 4221 4222 Notes: 4223 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4224 4225 `MatCopy()` copies the matrix entries of a matrix to another existing 4226 matrix (after first zeroing the second matrix). A related routine is 4227 `MatConvert()`, which first creates a new matrix and then copies the data. 4228 4229 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4230 @*/ 4231 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4232 { 4233 PetscInt i; 4234 4235 PetscFunctionBegin; 4236 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4237 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4238 PetscValidType(A, 1); 4239 PetscValidType(B, 2); 4240 PetscCheckSameComm(A, 1, B, 2); 4241 MatCheckPreallocated(B, 2); 4242 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4243 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4244 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, 4245 A->cmap->N, B->cmap->N); 4246 MatCheckPreallocated(A, 1); 4247 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4248 4249 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4250 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4251 else PetscCall(MatCopy_Basic(A, B, str)); 4252 4253 B->stencil.dim = A->stencil.dim; 4254 B->stencil.noc = A->stencil.noc; 4255 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4256 B->stencil.dims[i] = A->stencil.dims[i]; 4257 B->stencil.starts[i] = A->stencil.starts[i]; 4258 } 4259 4260 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4261 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4262 PetscFunctionReturn(PETSC_SUCCESS); 4263 } 4264 4265 /*@C 4266 MatConvert - Converts a matrix to another matrix, either of the same 4267 or different type. 4268 4269 Collective 4270 4271 Input Parameters: 4272 + mat - the matrix 4273 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4274 same type as the original matrix. 4275 - reuse - denotes if the destination matrix is to be created or reused. 4276 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 4277 `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). 4278 4279 Output Parameter: 4280 . M - pointer to place new matrix 4281 4282 Level: intermediate 4283 4284 Notes: 4285 `MatConvert()` first creates a new matrix and then copies the data from 4286 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4287 entries of one matrix to another already existing matrix context. 4288 4289 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4290 the MPI communicator of the generated matrix is always the same as the communicator 4291 of the input matrix. 4292 4293 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4294 @*/ 4295 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4296 { 4297 PetscBool sametype, issame, flg; 4298 PetscBool3 issymmetric, ishermitian; 4299 char convname[256], mtype[256]; 4300 Mat B; 4301 4302 PetscFunctionBegin; 4303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4304 PetscValidType(mat, 1); 4305 PetscAssertPointer(M, 4); 4306 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4307 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4308 MatCheckPreallocated(mat, 1); 4309 4310 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4311 if (flg) newtype = mtype; 4312 4313 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4314 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4315 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4316 if (reuse == MAT_REUSE_MATRIX) { 4317 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4318 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4319 } 4320 4321 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4322 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4323 PetscFunctionReturn(PETSC_SUCCESS); 4324 } 4325 4326 /* Cache Mat options because some converters use MatHeaderReplace */ 4327 issymmetric = mat->symmetric; 4328 ishermitian = mat->hermitian; 4329 4330 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4331 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4332 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4333 } else { 4334 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4335 const char *prefix[3] = {"seq", "mpi", ""}; 4336 PetscInt i; 4337 /* 4338 Order of precedence: 4339 0) See if newtype is a superclass of the current matrix. 4340 1) See if a specialized converter is known to the current matrix. 4341 2) See if a specialized converter is known to the desired matrix class. 4342 3) See if a good general converter is registered for the desired class 4343 (as of 6/27/03 only MATMPIADJ falls into this category). 4344 4) See if a good general converter is known for the current matrix. 4345 5) Use a really basic converter. 4346 */ 4347 4348 /* 0) See if newtype is a superclass of the current matrix. 4349 i.e mat is mpiaij and newtype is aij */ 4350 for (i = 0; i < 2; i++) { 4351 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4352 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4353 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4354 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4355 if (flg) { 4356 if (reuse == MAT_INPLACE_MATRIX) { 4357 PetscCall(PetscInfo(mat, "Early return\n")); 4358 PetscFunctionReturn(PETSC_SUCCESS); 4359 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4360 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4361 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4362 PetscFunctionReturn(PETSC_SUCCESS); 4363 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4364 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4365 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4366 PetscFunctionReturn(PETSC_SUCCESS); 4367 } 4368 } 4369 } 4370 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4371 for (i = 0; i < 3; i++) { 4372 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4373 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4374 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4378 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4379 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4380 if (conv) goto foundconv; 4381 } 4382 4383 /* 2) See if a specialized converter is known to the desired matrix class. */ 4384 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4385 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4386 PetscCall(MatSetType(B, newtype)); 4387 for (i = 0; i < 3; i++) { 4388 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4389 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4390 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4391 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4392 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4394 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4395 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4396 if (conv) { 4397 PetscCall(MatDestroy(&B)); 4398 goto foundconv; 4399 } 4400 } 4401 4402 /* 3) See if a good general converter is registered for the desired class */ 4403 conv = B->ops->convertfrom; 4404 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4405 PetscCall(MatDestroy(&B)); 4406 if (conv) goto foundconv; 4407 4408 /* 4) See if a good general converter is known for the current matrix */ 4409 if (mat->ops->convert) conv = mat->ops->convert; 4410 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4411 if (conv) goto foundconv; 4412 4413 /* 5) Use a really basic converter. */ 4414 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4415 conv = MatConvert_Basic; 4416 4417 foundconv: 4418 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4419 PetscCall((*conv)(mat, newtype, reuse, M)); 4420 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4421 /* the block sizes must be same if the mappings are copied over */ 4422 (*M)->rmap->bs = mat->rmap->bs; 4423 (*M)->cmap->bs = mat->cmap->bs; 4424 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4425 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4426 (*M)->rmap->mapping = mat->rmap->mapping; 4427 (*M)->cmap->mapping = mat->cmap->mapping; 4428 } 4429 (*M)->stencil.dim = mat->stencil.dim; 4430 (*M)->stencil.noc = mat->stencil.noc; 4431 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4432 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4433 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4434 } 4435 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4436 } 4437 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4438 4439 /* Copy Mat options */ 4440 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4441 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4442 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4443 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4444 PetscFunctionReturn(PETSC_SUCCESS); 4445 } 4446 4447 /*@C 4448 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4449 4450 Not Collective 4451 4452 Input Parameter: 4453 . mat - the matrix, must be a factored matrix 4454 4455 Output Parameter: 4456 . type - the string name of the package (do not free this string) 4457 4458 Level: intermediate 4459 4460 Fortran Note: 4461 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4462 4463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4464 @*/ 4465 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4466 { 4467 PetscErrorCode (*conv)(Mat, MatSolverType *); 4468 4469 PetscFunctionBegin; 4470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4471 PetscValidType(mat, 1); 4472 PetscAssertPointer(type, 2); 4473 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4474 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4475 if (conv) PetscCall((*conv)(mat, type)); 4476 else *type = MATSOLVERPETSC; 4477 PetscFunctionReturn(PETSC_SUCCESS); 4478 } 4479 4480 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4481 struct _MatSolverTypeForSpecifcType { 4482 MatType mtype; 4483 /* no entry for MAT_FACTOR_NONE */ 4484 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4485 MatSolverTypeForSpecifcType next; 4486 }; 4487 4488 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4489 struct _MatSolverTypeHolder { 4490 char *name; 4491 MatSolverTypeForSpecifcType handlers; 4492 MatSolverTypeHolder next; 4493 }; 4494 4495 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4496 4497 /*@C 4498 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4499 4500 Input Parameters: 4501 + package - name of the package, for example petsc or superlu 4502 . mtype - the matrix type that works with this package 4503 . ftype - the type of factorization supported by the package 4504 - createfactor - routine that will create the factored matrix ready to be used 4505 4506 Level: developer 4507 4508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4509 `MatGetFactor()` 4510 @*/ 4511 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4512 { 4513 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4514 PetscBool flg; 4515 MatSolverTypeForSpecifcType inext, iprev = NULL; 4516 4517 PetscFunctionBegin; 4518 PetscCall(MatInitializePackage()); 4519 if (!next) { 4520 PetscCall(PetscNew(&MatSolverTypeHolders)); 4521 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4522 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4523 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4524 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4525 PetscFunctionReturn(PETSC_SUCCESS); 4526 } 4527 while (next) { 4528 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4529 if (flg) { 4530 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4531 inext = next->handlers; 4532 while (inext) { 4533 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4534 if (flg) { 4535 inext->createfactor[(int)ftype - 1] = createfactor; 4536 PetscFunctionReturn(PETSC_SUCCESS); 4537 } 4538 iprev = inext; 4539 inext = inext->next; 4540 } 4541 PetscCall(PetscNew(&iprev->next)); 4542 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4543 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4544 PetscFunctionReturn(PETSC_SUCCESS); 4545 } 4546 prev = next; 4547 next = next->next; 4548 } 4549 PetscCall(PetscNew(&prev->next)); 4550 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4551 PetscCall(PetscNew(&prev->next->handlers)); 4552 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4553 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4554 PetscFunctionReturn(PETSC_SUCCESS); 4555 } 4556 4557 /*@C 4558 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4559 4560 Input Parameters: 4561 + 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 4562 . ftype - the type of factorization supported by the type 4563 - mtype - the matrix type that works with this type 4564 4565 Output Parameters: 4566 + foundtype - `PETSC_TRUE` if the type was registered 4567 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4568 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4569 4570 Calling sequence of `createfactor`: 4571 + A - the matrix providing the factor matrix 4572 . mtype - the `MatType` of the factor requested 4573 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4574 4575 Level: developer 4576 4577 Note: 4578 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4579 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4580 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4581 4582 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4583 `MatInitializePackage()` 4584 @*/ 4585 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4586 { 4587 MatSolverTypeHolder next = MatSolverTypeHolders; 4588 PetscBool flg; 4589 MatSolverTypeForSpecifcType inext; 4590 4591 PetscFunctionBegin; 4592 if (foundtype) *foundtype = PETSC_FALSE; 4593 if (foundmtype) *foundmtype = PETSC_FALSE; 4594 if (createfactor) *createfactor = NULL; 4595 4596 if (type) { 4597 while (next) { 4598 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4599 if (flg) { 4600 if (foundtype) *foundtype = PETSC_TRUE; 4601 inext = next->handlers; 4602 while (inext) { 4603 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4604 if (flg) { 4605 if (foundmtype) *foundmtype = PETSC_TRUE; 4606 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4607 PetscFunctionReturn(PETSC_SUCCESS); 4608 } 4609 inext = inext->next; 4610 } 4611 } 4612 next = next->next; 4613 } 4614 } else { 4615 while (next) { 4616 inext = next->handlers; 4617 while (inext) { 4618 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4619 if (flg && inext->createfactor[(int)ftype - 1]) { 4620 if (foundtype) *foundtype = PETSC_TRUE; 4621 if (foundmtype) *foundmtype = PETSC_TRUE; 4622 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4623 PetscFunctionReturn(PETSC_SUCCESS); 4624 } 4625 inext = inext->next; 4626 } 4627 next = next->next; 4628 } 4629 /* try with base classes inext->mtype */ 4630 next = MatSolverTypeHolders; 4631 while (next) { 4632 inext = next->handlers; 4633 while (inext) { 4634 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4635 if (flg && inext->createfactor[(int)ftype - 1]) { 4636 if (foundtype) *foundtype = PETSC_TRUE; 4637 if (foundmtype) *foundmtype = PETSC_TRUE; 4638 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4639 PetscFunctionReturn(PETSC_SUCCESS); 4640 } 4641 inext = inext->next; 4642 } 4643 next = next->next; 4644 } 4645 } 4646 PetscFunctionReturn(PETSC_SUCCESS); 4647 } 4648 4649 PetscErrorCode MatSolverTypeDestroy(void) 4650 { 4651 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4652 MatSolverTypeForSpecifcType inext, iprev; 4653 4654 PetscFunctionBegin; 4655 while (next) { 4656 PetscCall(PetscFree(next->name)); 4657 inext = next->handlers; 4658 while (inext) { 4659 PetscCall(PetscFree(inext->mtype)); 4660 iprev = inext; 4661 inext = inext->next; 4662 PetscCall(PetscFree(iprev)); 4663 } 4664 prev = next; 4665 next = next->next; 4666 PetscCall(PetscFree(prev)); 4667 } 4668 MatSolverTypeHolders = NULL; 4669 PetscFunctionReturn(PETSC_SUCCESS); 4670 } 4671 4672 /*@C 4673 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4674 4675 Logically Collective 4676 4677 Input Parameter: 4678 . mat - the matrix 4679 4680 Output Parameter: 4681 . flg - `PETSC_TRUE` if uses the ordering 4682 4683 Level: developer 4684 4685 Note: 4686 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4687 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4688 4689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4690 @*/ 4691 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4692 { 4693 PetscFunctionBegin; 4694 *flg = mat->canuseordering; 4695 PetscFunctionReturn(PETSC_SUCCESS); 4696 } 4697 4698 /*@C 4699 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4700 4701 Logically Collective 4702 4703 Input Parameters: 4704 + mat - the matrix obtained with `MatGetFactor()` 4705 - ftype - the factorization type to be used 4706 4707 Output Parameter: 4708 . otype - the preferred ordering type 4709 4710 Level: developer 4711 4712 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4713 @*/ 4714 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4715 { 4716 PetscFunctionBegin; 4717 *otype = mat->preferredordering[ftype]; 4718 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4719 PetscFunctionReturn(PETSC_SUCCESS); 4720 } 4721 4722 /*@C 4723 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4724 4725 Collective 4726 4727 Input Parameters: 4728 + mat - the matrix 4729 . 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 4730 the other criteria is returned 4731 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4732 4733 Output Parameter: 4734 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4735 4736 Options Database Keys: 4737 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4738 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4739 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4740 4741 Level: intermediate 4742 4743 Notes: 4744 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4745 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4746 4747 Users usually access the factorization solvers via `KSP` 4748 4749 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4750 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 4751 4752 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4753 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4754 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4755 4756 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4757 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4758 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4759 4760 Developer Note: 4761 This should actually be called `MatCreateFactor()` since it creates a new factor object 4762 4763 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4764 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4765 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4766 @*/ 4767 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4768 { 4769 PetscBool foundtype, foundmtype; 4770 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4771 4772 PetscFunctionBegin; 4773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4774 PetscValidType(mat, 1); 4775 4776 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4777 MatCheckPreallocated(mat, 1); 4778 4779 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4780 if (!foundtype) { 4781 if (type) { 4782 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], 4783 ((PetscObject)mat)->type_name, type); 4784 } else { 4785 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); 4786 } 4787 } 4788 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4789 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); 4790 4791 PetscCall((*conv)(mat, ftype, f)); 4792 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4793 PetscFunctionReturn(PETSC_SUCCESS); 4794 } 4795 4796 /*@C 4797 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4798 4799 Not Collective 4800 4801 Input Parameters: 4802 + mat - the matrix 4803 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4804 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4805 4806 Output Parameter: 4807 . flg - PETSC_TRUE if the factorization is available 4808 4809 Level: intermediate 4810 4811 Notes: 4812 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4813 such as pastix, superlu, mumps etc. 4814 4815 PETSc must have been ./configure to use the external solver, using the option --download-package 4816 4817 Developer Note: 4818 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4819 4820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4821 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4822 @*/ 4823 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4824 { 4825 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4826 4827 PetscFunctionBegin; 4828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4829 PetscValidType(mat, 1); 4830 PetscAssertPointer(flg, 4); 4831 4832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4833 MatCheckPreallocated(mat, 1); 4834 4835 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4836 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4837 PetscFunctionReturn(PETSC_SUCCESS); 4838 } 4839 4840 /*@ 4841 MatDuplicate - Duplicates a matrix including the non-zero structure. 4842 4843 Collective 4844 4845 Input Parameters: 4846 + mat - the matrix 4847 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4848 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4849 4850 Output Parameter: 4851 . M - pointer to place new matrix 4852 4853 Level: intermediate 4854 4855 Notes: 4856 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4857 4858 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4859 4860 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. 4861 4862 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4863 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4864 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4865 4866 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4867 @*/ 4868 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4869 { 4870 Mat B; 4871 VecType vtype; 4872 PetscInt i; 4873 PetscObject dm, container_h, container_d; 4874 void (*viewf)(void); 4875 4876 PetscFunctionBegin; 4877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4878 PetscValidType(mat, 1); 4879 PetscAssertPointer(M, 3); 4880 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4881 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4882 MatCheckPreallocated(mat, 1); 4883 4884 *M = NULL; 4885 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4886 PetscUseTypeMethod(mat, duplicate, op, M); 4887 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4888 B = *M; 4889 4890 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4891 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4892 PetscCall(MatGetVecType(mat, &vtype)); 4893 PetscCall(MatSetVecType(B, vtype)); 4894 4895 B->stencil.dim = mat->stencil.dim; 4896 B->stencil.noc = mat->stencil.noc; 4897 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4898 B->stencil.dims[i] = mat->stencil.dims[i]; 4899 B->stencil.starts[i] = mat->stencil.starts[i]; 4900 } 4901 4902 B->nooffproczerorows = mat->nooffproczerorows; 4903 B->nooffprocentries = mat->nooffprocentries; 4904 4905 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4906 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4907 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4908 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4909 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4910 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4911 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4912 PetscFunctionReturn(PETSC_SUCCESS); 4913 } 4914 4915 /*@ 4916 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4917 4918 Logically Collective 4919 4920 Input Parameter: 4921 . mat - the matrix 4922 4923 Output Parameter: 4924 . v - the diagonal of the matrix 4925 4926 Level: intermediate 4927 4928 Note: 4929 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4930 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4931 is larger than `ndiag`, the values of the remaining entries are unspecified. 4932 4933 Currently only correct in parallel for square matrices. 4934 4935 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4936 @*/ 4937 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4938 { 4939 PetscFunctionBegin; 4940 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4941 PetscValidType(mat, 1); 4942 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4943 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4944 MatCheckPreallocated(mat, 1); 4945 if (PetscDefined(USE_DEBUG)) { 4946 PetscInt nv, row, col, ndiag; 4947 4948 PetscCall(VecGetLocalSize(v, &nv)); 4949 PetscCall(MatGetLocalSize(mat, &row, &col)); 4950 ndiag = PetscMin(row, col); 4951 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); 4952 } 4953 4954 PetscUseTypeMethod(mat, getdiagonal, v); 4955 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4956 PetscFunctionReturn(PETSC_SUCCESS); 4957 } 4958 4959 /*@C 4960 MatGetRowMin - Gets the minimum value (of the real part) of each 4961 row of the matrix 4962 4963 Logically Collective 4964 4965 Input Parameter: 4966 . mat - the matrix 4967 4968 Output Parameters: 4969 + v - the vector for storing the maximums 4970 - idx - the indices of the column found for each row (optional) 4971 4972 Level: intermediate 4973 4974 Note: 4975 The result of this call are the same as if one converted the matrix to dense format 4976 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4977 4978 This code is only implemented for a couple of matrix formats. 4979 4980 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4981 `MatGetRowMax()` 4982 @*/ 4983 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4984 { 4985 PetscFunctionBegin; 4986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4987 PetscValidType(mat, 1); 4988 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4989 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4990 4991 if (!mat->cmap->N) { 4992 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4993 if (idx) { 4994 PetscInt i, m = mat->rmap->n; 4995 for (i = 0; i < m; i++) idx[i] = -1; 4996 } 4997 } else { 4998 MatCheckPreallocated(mat, 1); 4999 } 5000 PetscUseTypeMethod(mat, getrowmin, v, idx); 5001 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5002 PetscFunctionReturn(PETSC_SUCCESS); 5003 } 5004 5005 /*@C 5006 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5007 row of the matrix 5008 5009 Logically Collective 5010 5011 Input Parameter: 5012 . mat - the matrix 5013 5014 Output Parameters: 5015 + v - the vector for storing the minimums 5016 - idx - the indices of the column found for each row (or `NULL` if not needed) 5017 5018 Level: intermediate 5019 5020 Notes: 5021 if a row is completely empty or has only 0.0 values then the `idx` value for that 5022 row is 0 (the first column). 5023 5024 This code is only implemented for a couple of matrix formats. 5025 5026 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5027 @*/ 5028 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5029 { 5030 PetscFunctionBegin; 5031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5032 PetscValidType(mat, 1); 5033 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5034 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5035 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5036 5037 if (!mat->cmap->N) { 5038 PetscCall(VecSet(v, 0.0)); 5039 if (idx) { 5040 PetscInt i, m = mat->rmap->n; 5041 for (i = 0; i < m; i++) idx[i] = -1; 5042 } 5043 } else { 5044 MatCheckPreallocated(mat, 1); 5045 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5046 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5047 } 5048 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5049 PetscFunctionReturn(PETSC_SUCCESS); 5050 } 5051 5052 /*@C 5053 MatGetRowMax - Gets the maximum value (of the real part) of each 5054 row of the matrix 5055 5056 Logically Collective 5057 5058 Input Parameter: 5059 . mat - the matrix 5060 5061 Output Parameters: 5062 + v - the vector for storing the maximums 5063 - idx - the indices of the column found for each row (optional) 5064 5065 Level: intermediate 5066 5067 Notes: 5068 The result of this call are the same as if one converted the matrix to dense format 5069 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5070 5071 This code is only implemented for a couple of matrix formats. 5072 5073 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5074 @*/ 5075 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5076 { 5077 PetscFunctionBegin; 5078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5079 PetscValidType(mat, 1); 5080 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5081 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5082 5083 if (!mat->cmap->N) { 5084 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5085 if (idx) { 5086 PetscInt i, m = mat->rmap->n; 5087 for (i = 0; i < m; i++) idx[i] = -1; 5088 } 5089 } else { 5090 MatCheckPreallocated(mat, 1); 5091 PetscUseTypeMethod(mat, getrowmax, v, idx); 5092 } 5093 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5094 PetscFunctionReturn(PETSC_SUCCESS); 5095 } 5096 5097 /*@C 5098 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5099 row of the matrix 5100 5101 Logically Collective 5102 5103 Input Parameter: 5104 . mat - the matrix 5105 5106 Output Parameters: 5107 + v - the vector for storing the maximums 5108 - idx - the indices of the column found for each row (or `NULL` if not needed) 5109 5110 Level: intermediate 5111 5112 Notes: 5113 if a row is completely empty or has only 0.0 values then the `idx` value for that 5114 row is 0 (the first column). 5115 5116 This code is only implemented for a couple of matrix formats. 5117 5118 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5119 @*/ 5120 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5121 { 5122 PetscFunctionBegin; 5123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5124 PetscValidType(mat, 1); 5125 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5127 5128 if (!mat->cmap->N) { 5129 PetscCall(VecSet(v, 0.0)); 5130 if (idx) { 5131 PetscInt i, m = mat->rmap->n; 5132 for (i = 0; i < m; i++) idx[i] = -1; 5133 } 5134 } else { 5135 MatCheckPreallocated(mat, 1); 5136 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5137 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5138 } 5139 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5140 PetscFunctionReturn(PETSC_SUCCESS); 5141 } 5142 5143 /*@ 5144 MatGetRowSum - Gets the sum of each row of the matrix 5145 5146 Logically or Neighborhood Collective 5147 5148 Input Parameter: 5149 . mat - the matrix 5150 5151 Output Parameter: 5152 . v - the vector for storing the sum of rows 5153 5154 Level: intermediate 5155 5156 Note: 5157 This code is slow since it is not currently specialized for different formats 5158 5159 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5160 @*/ 5161 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5162 { 5163 Vec ones; 5164 5165 PetscFunctionBegin; 5166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5167 PetscValidType(mat, 1); 5168 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5169 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5170 MatCheckPreallocated(mat, 1); 5171 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5172 PetscCall(VecSet(ones, 1.)); 5173 PetscCall(MatMult(mat, ones, v)); 5174 PetscCall(VecDestroy(&ones)); 5175 PetscFunctionReturn(PETSC_SUCCESS); 5176 } 5177 5178 /*@ 5179 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5180 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5181 5182 Collective 5183 5184 Input Parameter: 5185 . mat - the matrix to provide the transpose 5186 5187 Output Parameter: 5188 . 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 5189 5190 Level: advanced 5191 5192 Note: 5193 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 5194 routine allows bypassing that call. 5195 5196 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5197 @*/ 5198 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5199 { 5200 PetscContainer rB = NULL; 5201 MatParentState *rb = NULL; 5202 5203 PetscFunctionBegin; 5204 PetscCall(PetscNew(&rb)); 5205 rb->id = ((PetscObject)mat)->id; 5206 rb->state = 0; 5207 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5208 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5209 PetscCall(PetscContainerSetPointer(rB, rb)); 5210 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5211 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5212 PetscCall(PetscObjectDereference((PetscObject)rB)); 5213 PetscFunctionReturn(PETSC_SUCCESS); 5214 } 5215 5216 /*@ 5217 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5218 5219 Collective 5220 5221 Input Parameters: 5222 + mat - the matrix to transpose 5223 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5224 5225 Output Parameter: 5226 . B - the transpose 5227 5228 Level: intermediate 5229 5230 Notes: 5231 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5232 5233 `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 5234 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5235 5236 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. 5237 5238 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5239 5240 If mat is unchanged from the last call this function returns immediately without recomputing the result 5241 5242 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5243 5244 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5245 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5246 @*/ 5247 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5248 { 5249 PetscContainer rB = NULL; 5250 MatParentState *rb = NULL; 5251 5252 PetscFunctionBegin; 5253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5254 PetscValidType(mat, 1); 5255 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5256 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5257 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5258 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5259 MatCheckPreallocated(mat, 1); 5260 if (reuse == MAT_REUSE_MATRIX) { 5261 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5262 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5263 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5264 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5265 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5266 } 5267 5268 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5269 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5270 PetscUseTypeMethod(mat, transpose, reuse, B); 5271 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5272 } 5273 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5274 5275 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5276 if (reuse != MAT_INPLACE_MATRIX) { 5277 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5278 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5279 rb->state = ((PetscObject)mat)->state; 5280 rb->nonzerostate = mat->nonzerostate; 5281 } 5282 PetscFunctionReturn(PETSC_SUCCESS); 5283 } 5284 5285 /*@ 5286 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5287 5288 Collective 5289 5290 Input Parameter: 5291 . A - the matrix to transpose 5292 5293 Output Parameter: 5294 . 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 5295 numerical portion. 5296 5297 Level: intermediate 5298 5299 Note: 5300 This is not supported for many matrix types, use `MatTranspose()` in those cases 5301 5302 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5303 @*/ 5304 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5305 { 5306 PetscFunctionBegin; 5307 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5308 PetscValidType(A, 1); 5309 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5310 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5311 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5312 PetscUseTypeMethod(A, transposesymbolic, B); 5313 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5314 5315 PetscCall(MatTransposeSetPrecursor(A, *B)); 5316 PetscFunctionReturn(PETSC_SUCCESS); 5317 } 5318 5319 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5320 { 5321 PetscContainer rB; 5322 MatParentState *rb; 5323 5324 PetscFunctionBegin; 5325 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5326 PetscValidType(A, 1); 5327 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5328 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5329 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5330 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5331 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5332 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5333 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5334 PetscFunctionReturn(PETSC_SUCCESS); 5335 } 5336 5337 /*@ 5338 MatIsTranspose - Test whether a matrix is another one's transpose, 5339 or its own, in which case it tests symmetry. 5340 5341 Collective 5342 5343 Input Parameters: 5344 + A - the matrix to test 5345 . B - the matrix to test against, this can equal the first parameter 5346 - tol - tolerance, differences between entries smaller than this are counted as zero 5347 5348 Output Parameter: 5349 . flg - the result 5350 5351 Level: intermediate 5352 5353 Notes: 5354 Only available for `MATAIJ` matrices. 5355 5356 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5357 test involves parallel copies of the block off-diagonal parts of the matrix. 5358 5359 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5360 @*/ 5361 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5362 { 5363 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5364 5365 PetscFunctionBegin; 5366 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5367 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5368 PetscAssertPointer(flg, 4); 5369 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5370 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5371 *flg = PETSC_FALSE; 5372 if (f && g) { 5373 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5374 PetscCall((*f)(A, B, tol, flg)); 5375 } else { 5376 MatType mattype; 5377 5378 PetscCall(MatGetType(f ? B : A, &mattype)); 5379 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5380 } 5381 PetscFunctionReturn(PETSC_SUCCESS); 5382 } 5383 5384 /*@ 5385 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5386 5387 Collective 5388 5389 Input Parameters: 5390 + mat - the matrix to transpose and complex conjugate 5391 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5392 5393 Output Parameter: 5394 . B - the Hermitian transpose 5395 5396 Level: intermediate 5397 5398 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5399 @*/ 5400 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5401 { 5402 PetscFunctionBegin; 5403 PetscCall(MatTranspose(mat, reuse, B)); 5404 #if defined(PETSC_USE_COMPLEX) 5405 PetscCall(MatConjugate(*B)); 5406 #endif 5407 PetscFunctionReturn(PETSC_SUCCESS); 5408 } 5409 5410 /*@ 5411 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5412 5413 Collective 5414 5415 Input Parameters: 5416 + A - the matrix to test 5417 . B - the matrix to test against, this can equal the first parameter 5418 - tol - tolerance, differences between entries smaller than this are counted as zero 5419 5420 Output Parameter: 5421 . flg - the result 5422 5423 Level: intermediate 5424 5425 Notes: 5426 Only available for `MATAIJ` matrices. 5427 5428 The sequential algorithm 5429 has a running time of the order of the number of nonzeros; the parallel 5430 test involves parallel copies of the block off-diagonal parts of the matrix. 5431 5432 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5433 @*/ 5434 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5435 { 5436 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5437 5438 PetscFunctionBegin; 5439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5440 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5441 PetscAssertPointer(flg, 4); 5442 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5443 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5444 if (f && g) { 5445 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5446 PetscCall((*f)(A, B, tol, flg)); 5447 } 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 /*@ 5452 MatPermute - Creates a new matrix with rows and columns permuted from the 5453 original. 5454 5455 Collective 5456 5457 Input Parameters: 5458 + mat - the matrix to permute 5459 . row - row permutation, each processor supplies only the permutation for its rows 5460 - col - column permutation, each processor supplies only the permutation for its columns 5461 5462 Output Parameter: 5463 . B - the permuted matrix 5464 5465 Level: advanced 5466 5467 Note: 5468 The index sets map from row/col of permuted matrix to row/col of original matrix. 5469 The index sets should be on the same communicator as mat and have the same local sizes. 5470 5471 Developer Note: 5472 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5473 exploit the fact that row and col are permutations, consider implementing the 5474 more general `MatCreateSubMatrix()` instead. 5475 5476 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5477 @*/ 5478 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5479 { 5480 PetscFunctionBegin; 5481 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5482 PetscValidType(mat, 1); 5483 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5484 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5485 PetscAssertPointer(B, 4); 5486 PetscCheckSameComm(mat, 1, row, 2); 5487 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5488 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5489 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5490 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5491 MatCheckPreallocated(mat, 1); 5492 5493 if (mat->ops->permute) { 5494 PetscUseTypeMethod(mat, permute, row, col, B); 5495 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5496 } else { 5497 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5498 } 5499 PetscFunctionReturn(PETSC_SUCCESS); 5500 } 5501 5502 /*@ 5503 MatEqual - Compares two matrices. 5504 5505 Collective 5506 5507 Input Parameters: 5508 + A - the first matrix 5509 - B - the second matrix 5510 5511 Output Parameter: 5512 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5513 5514 Level: intermediate 5515 5516 .seealso: [](ch_matrices), `Mat` 5517 @*/ 5518 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5519 { 5520 PetscFunctionBegin; 5521 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5522 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5523 PetscValidType(A, 1); 5524 PetscValidType(B, 2); 5525 PetscAssertPointer(flg, 3); 5526 PetscCheckSameComm(A, 1, B, 2); 5527 MatCheckPreallocated(A, 1); 5528 MatCheckPreallocated(B, 2); 5529 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5530 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5531 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, 5532 B->cmap->N); 5533 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5534 PetscUseTypeMethod(A, equal, B, flg); 5535 } else { 5536 PetscCall(MatMultEqual(A, B, 10, flg)); 5537 } 5538 PetscFunctionReturn(PETSC_SUCCESS); 5539 } 5540 5541 /*@ 5542 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5543 matrices that are stored as vectors. Either of the two scaling 5544 matrices can be `NULL`. 5545 5546 Collective 5547 5548 Input Parameters: 5549 + mat - the matrix to be scaled 5550 . l - the left scaling vector (or `NULL`) 5551 - r - the right scaling vector (or `NULL`) 5552 5553 Level: intermediate 5554 5555 Note: 5556 `MatDiagonalScale()` computes $A = LAR$, where 5557 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5558 The L scales the rows of the matrix, the R scales the columns of the matrix. 5559 5560 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5561 @*/ 5562 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5563 { 5564 PetscFunctionBegin; 5565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5566 PetscValidType(mat, 1); 5567 if (l) { 5568 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5569 PetscCheckSameComm(mat, 1, l, 2); 5570 } 5571 if (r) { 5572 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5573 PetscCheckSameComm(mat, 1, r, 3); 5574 } 5575 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5576 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5577 MatCheckPreallocated(mat, 1); 5578 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5579 5580 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5581 PetscUseTypeMethod(mat, diagonalscale, l, r); 5582 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5583 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5584 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5585 PetscFunctionReturn(PETSC_SUCCESS); 5586 } 5587 5588 /*@ 5589 MatScale - Scales all elements of a matrix by a given number. 5590 5591 Logically Collective 5592 5593 Input Parameters: 5594 + mat - the matrix to be scaled 5595 - a - the scaling value 5596 5597 Level: intermediate 5598 5599 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5600 @*/ 5601 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5602 { 5603 PetscFunctionBegin; 5604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5605 PetscValidType(mat, 1); 5606 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5607 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5608 PetscValidLogicalCollectiveScalar(mat, a, 2); 5609 MatCheckPreallocated(mat, 1); 5610 5611 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5612 if (a != (PetscScalar)1.0) { 5613 PetscUseTypeMethod(mat, scale, a); 5614 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5615 } 5616 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5617 PetscFunctionReturn(PETSC_SUCCESS); 5618 } 5619 5620 /*@ 5621 MatNorm - Calculates various norms of a matrix. 5622 5623 Collective 5624 5625 Input Parameters: 5626 + mat - the matrix 5627 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5628 5629 Output Parameter: 5630 . nrm - the resulting norm 5631 5632 Level: intermediate 5633 5634 .seealso: [](ch_matrices), `Mat` 5635 @*/ 5636 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5637 { 5638 PetscFunctionBegin; 5639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5640 PetscValidType(mat, 1); 5641 PetscAssertPointer(nrm, 3); 5642 5643 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5644 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5645 MatCheckPreallocated(mat, 1); 5646 5647 PetscUseTypeMethod(mat, norm, type, nrm); 5648 PetscFunctionReturn(PETSC_SUCCESS); 5649 } 5650 5651 /* 5652 This variable is used to prevent counting of MatAssemblyBegin() that 5653 are called from within a MatAssemblyEnd(). 5654 */ 5655 static PetscInt MatAssemblyEnd_InUse = 0; 5656 /*@ 5657 MatAssemblyBegin - Begins assembling the matrix. This routine should 5658 be called after completing all calls to `MatSetValues()`. 5659 5660 Collective 5661 5662 Input Parameters: 5663 + mat - the matrix 5664 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5665 5666 Level: beginner 5667 5668 Notes: 5669 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5670 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5671 5672 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5673 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5674 using the matrix. 5675 5676 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5677 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 5678 a global collective operation requiring all processes that share the matrix. 5679 5680 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5681 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5682 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5683 5684 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5685 @*/ 5686 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5687 { 5688 PetscFunctionBegin; 5689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5690 PetscValidType(mat, 1); 5691 MatCheckPreallocated(mat, 1); 5692 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5693 if (mat->assembled) { 5694 mat->was_assembled = PETSC_TRUE; 5695 mat->assembled = PETSC_FALSE; 5696 } 5697 5698 if (!MatAssemblyEnd_InUse) { 5699 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5700 PetscTryTypeMethod(mat, assemblybegin, type); 5701 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5702 } else PetscTryTypeMethod(mat, assemblybegin, type); 5703 PetscFunctionReturn(PETSC_SUCCESS); 5704 } 5705 5706 /*@ 5707 MatAssembled - Indicates if a matrix has been assembled and is ready for 5708 use; for example, in matrix-vector product. 5709 5710 Not Collective 5711 5712 Input Parameter: 5713 . mat - the matrix 5714 5715 Output Parameter: 5716 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5717 5718 Level: advanced 5719 5720 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5721 @*/ 5722 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5723 { 5724 PetscFunctionBegin; 5725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5726 PetscAssertPointer(assembled, 2); 5727 *assembled = mat->assembled; 5728 PetscFunctionReturn(PETSC_SUCCESS); 5729 } 5730 5731 /*@ 5732 MatAssemblyEnd - Completes assembling the matrix. This routine should 5733 be called after `MatAssemblyBegin()`. 5734 5735 Collective 5736 5737 Input Parameters: 5738 + mat - the matrix 5739 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5740 5741 Options Database Keys: 5742 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5743 . -mat_view ::ascii_info_detail - Prints more detailed info 5744 . -mat_view - Prints matrix in ASCII format 5745 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5746 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5747 . -display <name> - Sets display name (default is host) 5748 . -draw_pause <sec> - Sets number of seconds to pause after display 5749 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5750 . -viewer_socket_machine <machine> - Machine to use for socket 5751 . -viewer_socket_port <port> - Port number to use for socket 5752 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5753 5754 Level: beginner 5755 5756 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5757 @*/ 5758 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5759 { 5760 static PetscInt inassm = 0; 5761 PetscBool flg = PETSC_FALSE; 5762 5763 PetscFunctionBegin; 5764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5765 PetscValidType(mat, 1); 5766 5767 inassm++; 5768 MatAssemblyEnd_InUse++; 5769 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5770 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5771 PetscTryTypeMethod(mat, assemblyend, type); 5772 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5773 } else PetscTryTypeMethod(mat, assemblyend, type); 5774 5775 /* Flush assembly is not a true assembly */ 5776 if (type != MAT_FLUSH_ASSEMBLY) { 5777 if (mat->num_ass) { 5778 if (!mat->symmetry_eternal) { 5779 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5780 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5781 } 5782 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5783 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5784 } 5785 mat->num_ass++; 5786 mat->assembled = PETSC_TRUE; 5787 mat->ass_nonzerostate = mat->nonzerostate; 5788 } 5789 5790 mat->insertmode = NOT_SET_VALUES; 5791 MatAssemblyEnd_InUse--; 5792 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5793 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5794 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5795 5796 if (mat->checksymmetryonassembly) { 5797 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5798 if (flg) { 5799 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5800 } else { 5801 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5802 } 5803 } 5804 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5805 } 5806 inassm--; 5807 PetscFunctionReturn(PETSC_SUCCESS); 5808 } 5809 5810 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5811 /*@ 5812 MatSetOption - Sets a parameter option for a matrix. Some options 5813 may be specific to certain storage formats. Some options 5814 determine how values will be inserted (or added). Sorted, 5815 row-oriented input will generally assemble the fastest. The default 5816 is row-oriented. 5817 5818 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5819 5820 Input Parameters: 5821 + mat - the matrix 5822 . op - the option, one of those listed below (and possibly others), 5823 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5824 5825 Options Describing Matrix Structure: 5826 + `MAT_SPD` - symmetric positive definite 5827 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5828 . `MAT_HERMITIAN` - transpose is the complex conjugation 5829 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5830 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5831 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5832 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5833 5834 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5835 do not need to be computed (usually at a high cost) 5836 5837 Options For Use with `MatSetValues()`: 5838 Insert a logically dense subblock, which can be 5839 . `MAT_ROW_ORIENTED` - row-oriented (default) 5840 5841 These options reflect the data you pass in with `MatSetValues()`; it has 5842 nothing to do with how the data is stored internally in the matrix 5843 data structure. 5844 5845 When (re)assembling a matrix, we can restrict the input for 5846 efficiency/debugging purposes. These options include 5847 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5848 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5849 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5850 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5851 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5852 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5853 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5854 performance for very large process counts. 5855 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5856 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5857 functions, instead sending only neighbor messages. 5858 5859 Level: intermediate 5860 5861 Notes: 5862 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5863 5864 Some options are relevant only for particular matrix types and 5865 are thus ignored by others. Other options are not supported by 5866 certain matrix types and will generate an error message if set. 5867 5868 If using Fortran to compute a matrix, one may need to 5869 use the column-oriented option (or convert to the row-oriented 5870 format). 5871 5872 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5873 that would generate a new entry in the nonzero structure is instead 5874 ignored. Thus, if memory has not already been allocated for this particular 5875 data, then the insertion is ignored. For dense matrices, in which 5876 the entire array is allocated, no entries are ever ignored. 5877 Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5878 5879 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5880 that would generate a new entry in the nonzero structure instead produces 5881 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 5882 5883 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5884 that would generate a new entry that has not been preallocated will 5885 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5886 only.) This is a useful flag when debugging matrix memory preallocation. 5887 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5888 5889 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5890 other processors should be dropped, rather than stashed. 5891 This is useful if you know that the "owning" processor is also 5892 always generating the correct matrix entries, so that PETSc need 5893 not transfer duplicate entries generated on another processor. 5894 5895 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5896 searches during matrix assembly. When this flag is set, the hash table 5897 is created during the first matrix assembly. This hash table is 5898 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5899 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5900 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5901 supported by `MATMPIBAIJ` format only. 5902 5903 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5904 are kept in the nonzero structure 5905 5906 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5907 a zero location in the matrix 5908 5909 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5910 5911 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5912 zero row routines and thus improves performance for very large process counts. 5913 5914 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5915 part of the matrix (since they should match the upper triangular part). 5916 5917 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5918 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5919 with finite difference schemes with non-periodic boundary conditions. 5920 5921 Developer Note: 5922 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5923 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 5924 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5925 not changed. 5926 5927 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5928 @*/ 5929 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5930 { 5931 PetscFunctionBegin; 5932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5933 if (op > 0) { 5934 PetscValidLogicalCollectiveEnum(mat, op, 2); 5935 PetscValidLogicalCollectiveBool(mat, flg, 3); 5936 } 5937 5938 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); 5939 5940 switch (op) { 5941 case MAT_FORCE_DIAGONAL_ENTRIES: 5942 mat->force_diagonals = flg; 5943 PetscFunctionReturn(PETSC_SUCCESS); 5944 case MAT_NO_OFF_PROC_ENTRIES: 5945 mat->nooffprocentries = flg; 5946 PetscFunctionReturn(PETSC_SUCCESS); 5947 case MAT_SUBSET_OFF_PROC_ENTRIES: 5948 mat->assembly_subset = flg; 5949 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5950 #if !defined(PETSC_HAVE_MPIUNI) 5951 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5952 #endif 5953 mat->stash.first_assembly_done = PETSC_FALSE; 5954 } 5955 PetscFunctionReturn(PETSC_SUCCESS); 5956 case MAT_NO_OFF_PROC_ZERO_ROWS: 5957 mat->nooffproczerorows = flg; 5958 PetscFunctionReturn(PETSC_SUCCESS); 5959 case MAT_SPD: 5960 if (flg) { 5961 mat->spd = PETSC_BOOL3_TRUE; 5962 mat->symmetric = PETSC_BOOL3_TRUE; 5963 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5964 } else { 5965 mat->spd = PETSC_BOOL3_FALSE; 5966 } 5967 break; 5968 case MAT_SYMMETRIC: 5969 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5970 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5971 #if !defined(PETSC_USE_COMPLEX) 5972 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5973 #endif 5974 break; 5975 case MAT_HERMITIAN: 5976 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5977 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5978 #if !defined(PETSC_USE_COMPLEX) 5979 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5980 #endif 5981 break; 5982 case MAT_STRUCTURALLY_SYMMETRIC: 5983 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5984 break; 5985 case MAT_SYMMETRY_ETERNAL: 5986 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"); 5987 mat->symmetry_eternal = flg; 5988 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5989 break; 5990 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5991 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"); 5992 mat->structural_symmetry_eternal = flg; 5993 break; 5994 case MAT_SPD_ETERNAL: 5995 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"); 5996 mat->spd_eternal = flg; 5997 if (flg) { 5998 mat->structural_symmetry_eternal = PETSC_TRUE; 5999 mat->symmetry_eternal = PETSC_TRUE; 6000 } 6001 break; 6002 case MAT_STRUCTURE_ONLY: 6003 mat->structure_only = flg; 6004 break; 6005 case MAT_SORTED_FULL: 6006 mat->sortedfull = flg; 6007 break; 6008 default: 6009 break; 6010 } 6011 PetscTryTypeMethod(mat, setoption, op, flg); 6012 PetscFunctionReturn(PETSC_SUCCESS); 6013 } 6014 6015 /*@ 6016 MatGetOption - Gets a parameter option that has been set for a matrix. 6017 6018 Logically Collective 6019 6020 Input Parameters: 6021 + mat - the matrix 6022 - op - the option, this only responds to certain options, check the code for which ones 6023 6024 Output Parameter: 6025 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6026 6027 Level: intermediate 6028 6029 Notes: 6030 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6031 6032 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6033 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6034 6035 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6036 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6037 @*/ 6038 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6039 { 6040 PetscFunctionBegin; 6041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6042 PetscValidType(mat, 1); 6043 6044 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); 6045 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()"); 6046 6047 switch (op) { 6048 case MAT_NO_OFF_PROC_ENTRIES: 6049 *flg = mat->nooffprocentries; 6050 break; 6051 case MAT_NO_OFF_PROC_ZERO_ROWS: 6052 *flg = mat->nooffproczerorows; 6053 break; 6054 case MAT_SYMMETRIC: 6055 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6056 break; 6057 case MAT_HERMITIAN: 6058 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6059 break; 6060 case MAT_STRUCTURALLY_SYMMETRIC: 6061 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6062 break; 6063 case MAT_SPD: 6064 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6065 break; 6066 case MAT_SYMMETRY_ETERNAL: 6067 *flg = mat->symmetry_eternal; 6068 break; 6069 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6070 *flg = mat->symmetry_eternal; 6071 break; 6072 default: 6073 break; 6074 } 6075 PetscFunctionReturn(PETSC_SUCCESS); 6076 } 6077 6078 /*@ 6079 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6080 this routine retains the old nonzero structure. 6081 6082 Logically Collective 6083 6084 Input Parameter: 6085 . mat - the matrix 6086 6087 Level: intermediate 6088 6089 Note: 6090 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. 6091 See the Performance chapter of the users manual for information on preallocating matrices. 6092 6093 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6094 @*/ 6095 PetscErrorCode MatZeroEntries(Mat mat) 6096 { 6097 PetscFunctionBegin; 6098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6099 PetscValidType(mat, 1); 6100 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6101 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"); 6102 MatCheckPreallocated(mat, 1); 6103 6104 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6105 PetscUseTypeMethod(mat, zeroentries); 6106 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6107 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6108 PetscFunctionReturn(PETSC_SUCCESS); 6109 } 6110 6111 /*@ 6112 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6113 of a set of rows and columns of a matrix. 6114 6115 Collective 6116 6117 Input Parameters: 6118 + mat - the matrix 6119 . numRows - the number of rows/columns to zero 6120 . rows - the global row indices 6121 . diag - value put in the diagonal of the eliminated rows 6122 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6123 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6124 6125 Level: intermediate 6126 6127 Notes: 6128 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6129 6130 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6131 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 6132 6133 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6134 Krylov method to take advantage of the known solution on the zeroed rows. 6135 6136 For the parallel case, all processes that share the matrix (i.e., 6137 those in the communicator used for matrix creation) MUST call this 6138 routine, regardless of whether any rows being zeroed are owned by 6139 them. 6140 6141 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6142 6143 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6144 list only rows local to itself). 6145 6146 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6147 6148 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6149 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6150 @*/ 6151 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6152 { 6153 PetscFunctionBegin; 6154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6155 PetscValidType(mat, 1); 6156 if (numRows) PetscAssertPointer(rows, 3); 6157 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6158 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6159 MatCheckPreallocated(mat, 1); 6160 6161 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6162 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6163 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6164 PetscFunctionReturn(PETSC_SUCCESS); 6165 } 6166 6167 /*@ 6168 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6169 of a set of rows and columns of a matrix. 6170 6171 Collective 6172 6173 Input Parameters: 6174 + mat - the matrix 6175 . is - the rows to zero 6176 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6177 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6178 - b - optional vector of right hand side, that will be adjusted by provided solution 6179 6180 Level: intermediate 6181 6182 Note: 6183 See `MatZeroRowsColumns()` for details on how this routine operates. 6184 6185 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6186 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6187 @*/ 6188 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6189 { 6190 PetscInt numRows; 6191 const PetscInt *rows; 6192 6193 PetscFunctionBegin; 6194 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6195 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6196 PetscValidType(mat, 1); 6197 PetscValidType(is, 2); 6198 PetscCall(ISGetLocalSize(is, &numRows)); 6199 PetscCall(ISGetIndices(is, &rows)); 6200 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6201 PetscCall(ISRestoreIndices(is, &rows)); 6202 PetscFunctionReturn(PETSC_SUCCESS); 6203 } 6204 6205 /*@ 6206 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6207 of a set of rows of a matrix. 6208 6209 Collective 6210 6211 Input Parameters: 6212 + mat - the matrix 6213 . numRows - the number of rows to zero 6214 . rows - the global row indices 6215 . diag - value put in the diagonal of the zeroed rows 6216 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6217 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6218 6219 Level: intermediate 6220 6221 Notes: 6222 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6223 6224 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6225 6226 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6227 Krylov method to take advantage of the known solution on the zeroed rows. 6228 6229 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) 6230 from the matrix. 6231 6232 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6233 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 6234 formats this does not alter the nonzero structure. 6235 6236 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6237 of the matrix is not changed the values are 6238 merely zeroed. 6239 6240 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6241 formats can optionally remove the main diagonal entry from the 6242 nonzero structure as well, by passing 0.0 as the final argument). 6243 6244 For the parallel case, all processes that share the matrix (i.e., 6245 those in the communicator used for matrix creation) MUST call this 6246 routine, regardless of whether any rows being zeroed are owned by 6247 them. 6248 6249 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6250 list only rows local to itself). 6251 6252 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6253 owns that are to be zeroed. This saves a global synchronization in the implementation. 6254 6255 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6256 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6257 @*/ 6258 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6259 { 6260 PetscFunctionBegin; 6261 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6262 PetscValidType(mat, 1); 6263 if (numRows) PetscAssertPointer(rows, 3); 6264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6265 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6266 MatCheckPreallocated(mat, 1); 6267 6268 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6269 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6270 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6271 PetscFunctionReturn(PETSC_SUCCESS); 6272 } 6273 6274 /*@ 6275 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6276 of a set of rows of a matrix. 6277 6278 Collective 6279 6280 Input Parameters: 6281 + mat - the matrix 6282 . is - index set of rows to remove (if `NULL` then no row is removed) 6283 . diag - value put in all diagonals of eliminated rows 6284 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6285 - b - optional vector of right hand side, that will be adjusted by provided solution 6286 6287 Level: intermediate 6288 6289 Note: 6290 See `MatZeroRows()` for details on how this routine operates. 6291 6292 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6293 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6294 @*/ 6295 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6296 { 6297 PetscInt numRows = 0; 6298 const PetscInt *rows = NULL; 6299 6300 PetscFunctionBegin; 6301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6302 PetscValidType(mat, 1); 6303 if (is) { 6304 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6305 PetscCall(ISGetLocalSize(is, &numRows)); 6306 PetscCall(ISGetIndices(is, &rows)); 6307 } 6308 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6309 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6310 PetscFunctionReturn(PETSC_SUCCESS); 6311 } 6312 6313 /*@ 6314 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6315 of a set of rows of a matrix. These rows must be local to the process. 6316 6317 Collective 6318 6319 Input Parameters: 6320 + mat - the matrix 6321 . numRows - the number of rows to remove 6322 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6323 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6324 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6325 - b - optional vector of right hand side, that will be adjusted by provided solution 6326 6327 Level: intermediate 6328 6329 Notes: 6330 See `MatZeroRows()` for details on how this routine operates. 6331 6332 The grid coordinates are across the entire grid, not just the local portion 6333 6334 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6335 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6336 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6337 `DM_BOUNDARY_PERIODIC` boundary type. 6338 6339 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 6340 a single value per point) you can skip filling those indices. 6341 6342 Fortran Note: 6343 `idxm` and `idxn` should be declared as 6344 $ MatStencil idxm(4, m) 6345 and the values inserted using 6346 .vb 6347 idxm(MatStencil_i, 1) = i 6348 idxm(MatStencil_j, 1) = j 6349 idxm(MatStencil_k, 1) = k 6350 idxm(MatStencil_c, 1) = c 6351 etc 6352 .ve 6353 6354 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6355 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6356 @*/ 6357 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6358 { 6359 PetscInt dim = mat->stencil.dim; 6360 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6361 PetscInt *dims = mat->stencil.dims + 1; 6362 PetscInt *starts = mat->stencil.starts; 6363 PetscInt *dxm = (PetscInt *)rows; 6364 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6365 6366 PetscFunctionBegin; 6367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6368 PetscValidType(mat, 1); 6369 if (numRows) PetscAssertPointer(rows, 3); 6370 6371 PetscCall(PetscMalloc1(numRows, &jdxm)); 6372 for (i = 0; i < numRows; ++i) { 6373 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6374 for (j = 0; j < 3 - sdim; ++j) dxm++; 6375 /* Local index in X dir */ 6376 tmp = *dxm++ - starts[0]; 6377 /* Loop over remaining dimensions */ 6378 for (j = 0; j < dim - 1; ++j) { 6379 /* If nonlocal, set index to be negative */ 6380 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6381 /* Update local index */ 6382 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6383 } 6384 /* Skip component slot if necessary */ 6385 if (mat->stencil.noc) dxm++; 6386 /* Local row number */ 6387 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6388 } 6389 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6390 PetscCall(PetscFree(jdxm)); 6391 PetscFunctionReturn(PETSC_SUCCESS); 6392 } 6393 6394 /*@ 6395 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6396 of a set of rows and columns of a matrix. 6397 6398 Collective 6399 6400 Input Parameters: 6401 + mat - the matrix 6402 . numRows - the number of rows/columns to remove 6403 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6404 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6405 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6406 - b - optional vector of right hand side, that will be adjusted by provided solution 6407 6408 Level: intermediate 6409 6410 Notes: 6411 See `MatZeroRowsColumns()` for details on how this routine operates. 6412 6413 The grid coordinates are across the entire grid, not just the local portion 6414 6415 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6416 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6417 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6418 `DM_BOUNDARY_PERIODIC` boundary type. 6419 6420 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 6421 a single value per point) you can skip filling those indices. 6422 6423 Fortran Note: 6424 `idxm` and `idxn` should be declared as 6425 $ MatStencil idxm(4, m) 6426 and the values inserted using 6427 .vb 6428 idxm(MatStencil_i, 1) = i 6429 idxm(MatStencil_j, 1) = j 6430 idxm(MatStencil_k, 1) = k 6431 idxm(MatStencil_c, 1) = c 6432 etc 6433 .ve 6434 6435 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6436 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6437 @*/ 6438 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6439 { 6440 PetscInt dim = mat->stencil.dim; 6441 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6442 PetscInt *dims = mat->stencil.dims + 1; 6443 PetscInt *starts = mat->stencil.starts; 6444 PetscInt *dxm = (PetscInt *)rows; 6445 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6446 6447 PetscFunctionBegin; 6448 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6449 PetscValidType(mat, 1); 6450 if (numRows) PetscAssertPointer(rows, 3); 6451 6452 PetscCall(PetscMalloc1(numRows, &jdxm)); 6453 for (i = 0; i < numRows; ++i) { 6454 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6455 for (j = 0; j < 3 - sdim; ++j) dxm++; 6456 /* Local index in X dir */ 6457 tmp = *dxm++ - starts[0]; 6458 /* Loop over remaining dimensions */ 6459 for (j = 0; j < dim - 1; ++j) { 6460 /* If nonlocal, set index to be negative */ 6461 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6462 /* Update local index */ 6463 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6464 } 6465 /* Skip component slot if necessary */ 6466 if (mat->stencil.noc) dxm++; 6467 /* Local row number */ 6468 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6469 } 6470 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6471 PetscCall(PetscFree(jdxm)); 6472 PetscFunctionReturn(PETSC_SUCCESS); 6473 } 6474 6475 /*@C 6476 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6477 of a set of rows of a matrix; using local numbering of rows. 6478 6479 Collective 6480 6481 Input Parameters: 6482 + mat - the matrix 6483 . numRows - the number of rows to remove 6484 . rows - the local row indices 6485 . diag - value put in all diagonals of eliminated rows 6486 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6487 - b - optional vector of right hand side, that will be adjusted by provided solution 6488 6489 Level: intermediate 6490 6491 Notes: 6492 Before calling `MatZeroRowsLocal()`, the user must first set the 6493 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6494 6495 See `MatZeroRows()` for details on how this routine operates. 6496 6497 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6498 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6499 @*/ 6500 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6501 { 6502 PetscFunctionBegin; 6503 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6504 PetscValidType(mat, 1); 6505 if (numRows) PetscAssertPointer(rows, 3); 6506 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6507 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6508 MatCheckPreallocated(mat, 1); 6509 6510 if (mat->ops->zerorowslocal) { 6511 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6512 } else { 6513 IS is, newis; 6514 const PetscInt *newRows; 6515 6516 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6517 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6518 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6519 PetscCall(ISGetIndices(newis, &newRows)); 6520 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6521 PetscCall(ISRestoreIndices(newis, &newRows)); 6522 PetscCall(ISDestroy(&newis)); 6523 PetscCall(ISDestroy(&is)); 6524 } 6525 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6526 PetscFunctionReturn(PETSC_SUCCESS); 6527 } 6528 6529 /*@ 6530 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6531 of a set of rows of a matrix; using local numbering of rows. 6532 6533 Collective 6534 6535 Input Parameters: 6536 + mat - the matrix 6537 . is - index set of rows to remove 6538 . diag - value put in all diagonals of eliminated rows 6539 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6540 - b - optional vector of right hand side, that will be adjusted by provided solution 6541 6542 Level: intermediate 6543 6544 Notes: 6545 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6546 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6547 6548 See `MatZeroRows()` for details on how this routine operates. 6549 6550 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6551 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6552 @*/ 6553 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6554 { 6555 PetscInt numRows; 6556 const PetscInt *rows; 6557 6558 PetscFunctionBegin; 6559 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6560 PetscValidType(mat, 1); 6561 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6562 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6563 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6564 MatCheckPreallocated(mat, 1); 6565 6566 PetscCall(ISGetLocalSize(is, &numRows)); 6567 PetscCall(ISGetIndices(is, &rows)); 6568 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6569 PetscCall(ISRestoreIndices(is, &rows)); 6570 PetscFunctionReturn(PETSC_SUCCESS); 6571 } 6572 6573 /*@ 6574 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6575 of a set of rows and columns of a matrix; using local numbering of rows. 6576 6577 Collective 6578 6579 Input Parameters: 6580 + mat - the matrix 6581 . numRows - the number of rows to remove 6582 . rows - the global row indices 6583 . diag - value put in all diagonals of eliminated rows 6584 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6585 - b - optional vector of right hand side, that will be adjusted by provided solution 6586 6587 Level: intermediate 6588 6589 Notes: 6590 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6591 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6592 6593 See `MatZeroRowsColumns()` for details on how this routine operates. 6594 6595 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6596 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6597 @*/ 6598 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6599 { 6600 IS is, newis; 6601 const PetscInt *newRows; 6602 6603 PetscFunctionBegin; 6604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6605 PetscValidType(mat, 1); 6606 if (numRows) PetscAssertPointer(rows, 3); 6607 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6608 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6609 MatCheckPreallocated(mat, 1); 6610 6611 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6612 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6613 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6614 PetscCall(ISGetIndices(newis, &newRows)); 6615 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6616 PetscCall(ISRestoreIndices(newis, &newRows)); 6617 PetscCall(ISDestroy(&newis)); 6618 PetscCall(ISDestroy(&is)); 6619 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6620 PetscFunctionReturn(PETSC_SUCCESS); 6621 } 6622 6623 /*@ 6624 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6625 of a set of rows and columns of a matrix; using local numbering of rows. 6626 6627 Collective 6628 6629 Input Parameters: 6630 + mat - the matrix 6631 . is - index set of rows to remove 6632 . diag - value put in all diagonals of eliminated rows 6633 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6634 - b - optional vector of right hand side, that will be adjusted by provided solution 6635 6636 Level: intermediate 6637 6638 Notes: 6639 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6640 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6641 6642 See `MatZeroRowsColumns()` for details on how this routine operates. 6643 6644 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6645 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6646 @*/ 6647 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6648 { 6649 PetscInt numRows; 6650 const PetscInt *rows; 6651 6652 PetscFunctionBegin; 6653 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6654 PetscValidType(mat, 1); 6655 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6656 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6657 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6658 MatCheckPreallocated(mat, 1); 6659 6660 PetscCall(ISGetLocalSize(is, &numRows)); 6661 PetscCall(ISGetIndices(is, &rows)); 6662 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6663 PetscCall(ISRestoreIndices(is, &rows)); 6664 PetscFunctionReturn(PETSC_SUCCESS); 6665 } 6666 6667 /*@C 6668 MatGetSize - Returns the numbers of rows and columns in a matrix. 6669 6670 Not Collective 6671 6672 Input Parameter: 6673 . mat - the matrix 6674 6675 Output Parameters: 6676 + m - the number of global rows 6677 - n - the number of global columns 6678 6679 Level: beginner 6680 6681 Note: 6682 Both output parameters can be `NULL` on input. 6683 6684 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6685 @*/ 6686 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6687 { 6688 PetscFunctionBegin; 6689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6690 if (m) *m = mat->rmap->N; 6691 if (n) *n = mat->cmap->N; 6692 PetscFunctionReturn(PETSC_SUCCESS); 6693 } 6694 6695 /*@C 6696 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6697 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6698 6699 Not Collective 6700 6701 Input Parameter: 6702 . mat - the matrix 6703 6704 Output Parameters: 6705 + m - the number of local rows, use `NULL` to not obtain this value 6706 - n - the number of local columns, use `NULL` to not obtain this value 6707 6708 Level: beginner 6709 6710 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6711 @*/ 6712 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6713 { 6714 PetscFunctionBegin; 6715 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6716 if (m) PetscAssertPointer(m, 2); 6717 if (n) PetscAssertPointer(n, 3); 6718 if (m) *m = mat->rmap->n; 6719 if (n) *n = mat->cmap->n; 6720 PetscFunctionReturn(PETSC_SUCCESS); 6721 } 6722 6723 /*@C 6724 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6725 vector one multiplies this matrix by that are owned by this processor. 6726 6727 Not Collective, unless matrix has not been allocated, then collective 6728 6729 Input Parameter: 6730 . mat - the matrix 6731 6732 Output Parameters: 6733 + m - the global index of the first local column, use `NULL` to not obtain this value 6734 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6735 6736 Level: developer 6737 6738 Note: 6739 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6740 Layouts](sec_matlayout) for details on matrix layouts. 6741 6742 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6743 @*/ 6744 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6745 { 6746 PetscFunctionBegin; 6747 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6748 PetscValidType(mat, 1); 6749 if (m) PetscAssertPointer(m, 2); 6750 if (n) PetscAssertPointer(n, 3); 6751 MatCheckPreallocated(mat, 1); 6752 if (m) *m = mat->cmap->rstart; 6753 if (n) *n = mat->cmap->rend; 6754 PetscFunctionReturn(PETSC_SUCCESS); 6755 } 6756 6757 /*@C 6758 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6759 this MPI process. 6760 6761 Not Collective 6762 6763 Input Parameter: 6764 . mat - the matrix 6765 6766 Output Parameters: 6767 + m - the global index of the first local row, use `NULL` to not obtain this value 6768 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6769 6770 Level: beginner 6771 6772 Note: 6773 For all matrices it returns the range of matrix rows associated with rows of a vector that 6774 would contain the result of a matrix vector product with this matrix. See [Matrix 6775 Layouts](sec_matlayout) for details on matrix layouts. 6776 6777 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6778 `PetscLayout` 6779 @*/ 6780 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6781 { 6782 PetscFunctionBegin; 6783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6784 PetscValidType(mat, 1); 6785 if (m) PetscAssertPointer(m, 2); 6786 if (n) PetscAssertPointer(n, 3); 6787 MatCheckPreallocated(mat, 1); 6788 if (m) *m = mat->rmap->rstart; 6789 if (n) *n = mat->rmap->rend; 6790 PetscFunctionReturn(PETSC_SUCCESS); 6791 } 6792 6793 /*@C 6794 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6795 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6796 6797 Not Collective, unless matrix has not been allocated 6798 6799 Input Parameter: 6800 . mat - the matrix 6801 6802 Output Parameter: 6803 . ranges - start of each processors portion plus one more than the total length at the end 6804 6805 Level: beginner 6806 6807 Note: 6808 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6809 would contain the result of a matrix vector product with this matrix. See [Matrix 6810 Layouts](sec_matlayout) for details on matrix layouts. 6811 6812 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6813 @*/ 6814 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6815 { 6816 PetscFunctionBegin; 6817 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6818 PetscValidType(mat, 1); 6819 MatCheckPreallocated(mat, 1); 6820 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6821 PetscFunctionReturn(PETSC_SUCCESS); 6822 } 6823 6824 /*@C 6825 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6826 vector one multiplies this vector by that are owned by each processor. 6827 6828 Not Collective, unless matrix has not been allocated 6829 6830 Input Parameter: 6831 . mat - the matrix 6832 6833 Output Parameter: 6834 . ranges - start of each processors portion plus one more than the total length at the end 6835 6836 Level: beginner 6837 6838 Note: 6839 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6840 Layouts](sec_matlayout) for details on matrix layouts. 6841 6842 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6843 @*/ 6844 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6845 { 6846 PetscFunctionBegin; 6847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6848 PetscValidType(mat, 1); 6849 MatCheckPreallocated(mat, 1); 6850 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6851 PetscFunctionReturn(PETSC_SUCCESS); 6852 } 6853 6854 /*@C 6855 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6856 6857 Not Collective 6858 6859 Input Parameter: 6860 . A - matrix 6861 6862 Output Parameters: 6863 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6864 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6865 6866 Level: intermediate 6867 6868 Note: 6869 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6870 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6871 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6872 details on matrix layouts. 6873 6874 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6875 @*/ 6876 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6877 { 6878 PetscErrorCode (*f)(Mat, IS *, IS *); 6879 6880 PetscFunctionBegin; 6881 MatCheckPreallocated(A, 1); 6882 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6883 if (f) { 6884 PetscCall((*f)(A, rows, cols)); 6885 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6886 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6887 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6888 } 6889 PetscFunctionReturn(PETSC_SUCCESS); 6890 } 6891 6892 /*@C 6893 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6894 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6895 to complete the factorization. 6896 6897 Collective 6898 6899 Input Parameters: 6900 + fact - the factorized matrix obtained with `MatGetFactor()` 6901 . mat - the matrix 6902 . row - row permutation 6903 . col - column permutation 6904 - info - structure containing 6905 .vb 6906 levels - number of levels of fill. 6907 expected fill - as ratio of original fill. 6908 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6909 missing diagonal entries) 6910 .ve 6911 6912 Level: developer 6913 6914 Notes: 6915 See [Matrix Factorization](sec_matfactor) for additional information. 6916 6917 Most users should employ the `KSP` interface for linear solvers 6918 instead of working directly with matrix algebra routines such as this. 6919 See, e.g., `KSPCreate()`. 6920 6921 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 6922 6923 Developer Note: 6924 The Fortran interface is not autogenerated as the 6925 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6926 6927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6928 `MatGetOrdering()`, `MatFactorInfo` 6929 @*/ 6930 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6931 { 6932 PetscFunctionBegin; 6933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6934 PetscValidType(mat, 2); 6935 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6936 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6937 PetscAssertPointer(info, 5); 6938 PetscAssertPointer(fact, 1); 6939 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6940 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6941 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6942 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6943 MatCheckPreallocated(mat, 2); 6944 6945 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6946 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6947 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6948 PetscFunctionReturn(PETSC_SUCCESS); 6949 } 6950 6951 /*@C 6952 MatICCFactorSymbolic - Performs symbolic incomplete 6953 Cholesky factorization for a symmetric matrix. Use 6954 `MatCholeskyFactorNumeric()` to complete the factorization. 6955 6956 Collective 6957 6958 Input Parameters: 6959 + fact - the factorized matrix obtained with `MatGetFactor()` 6960 . mat - the matrix to be factored 6961 . perm - row and column permutation 6962 - info - structure containing 6963 .vb 6964 levels - number of levels of fill. 6965 expected fill - as ratio of original fill. 6966 .ve 6967 6968 Level: developer 6969 6970 Notes: 6971 Most users should employ the `KSP` interface for linear solvers 6972 instead of working directly with matrix algebra routines such as this. 6973 See, e.g., `KSPCreate()`. 6974 6975 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 6976 6977 Developer Note: 6978 The Fortran interface is not autogenerated as the 6979 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6980 6981 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6982 @*/ 6983 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6984 { 6985 PetscFunctionBegin; 6986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6987 PetscValidType(mat, 2); 6988 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6989 PetscAssertPointer(info, 4); 6990 PetscAssertPointer(fact, 1); 6991 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6992 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6993 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6994 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6995 MatCheckPreallocated(mat, 2); 6996 6997 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6998 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6999 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7000 PetscFunctionReturn(PETSC_SUCCESS); 7001 } 7002 7003 /*@C 7004 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7005 points to an array of valid matrices, they may be reused to store the new 7006 submatrices. 7007 7008 Collective 7009 7010 Input Parameters: 7011 + mat - the matrix 7012 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7013 . irow - index set of rows to extract 7014 . icol - index set of columns to extract 7015 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7016 7017 Output Parameter: 7018 . submat - the array of submatrices 7019 7020 Level: advanced 7021 7022 Notes: 7023 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7024 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7025 to extract a parallel submatrix. 7026 7027 Some matrix types place restrictions on the row and column 7028 indices, such as that they be sorted or that they be equal to each other. 7029 7030 The index sets may not have duplicate entries. 7031 7032 When extracting submatrices from a parallel matrix, each processor can 7033 form a different submatrix by setting the rows and columns of its 7034 individual index sets according to the local submatrix desired. 7035 7036 When finished using the submatrices, the user should destroy 7037 them with `MatDestroySubMatrices()`. 7038 7039 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7040 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7041 7042 This routine creates the matrices in submat; you should NOT create them before 7043 calling it. It also allocates the array of matrix pointers submat. 7044 7045 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7046 request one row/column in a block, they must request all rows/columns that are in 7047 that block. For example, if the block size is 2 you cannot request just row 0 and 7048 column 0. 7049 7050 Fortran Note: 7051 The Fortran interface is slightly different from that given below; it 7052 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7053 7054 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7055 @*/ 7056 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7057 { 7058 PetscInt i; 7059 PetscBool eq; 7060 7061 PetscFunctionBegin; 7062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7063 PetscValidType(mat, 1); 7064 if (n) { 7065 PetscAssertPointer(irow, 3); 7066 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7067 PetscAssertPointer(icol, 4); 7068 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7069 } 7070 PetscAssertPointer(submat, 6); 7071 if (n && scall == MAT_REUSE_MATRIX) { 7072 PetscAssertPointer(*submat, 6); 7073 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7074 } 7075 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7076 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7077 MatCheckPreallocated(mat, 1); 7078 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7079 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7080 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7081 for (i = 0; i < n; i++) { 7082 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7083 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7084 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7085 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7086 if (mat->boundtocpu && mat->bindingpropagates) { 7087 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7088 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7089 } 7090 #endif 7091 } 7092 PetscFunctionReturn(PETSC_SUCCESS); 7093 } 7094 7095 /*@C 7096 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7097 7098 Collective 7099 7100 Input Parameters: 7101 + mat - the matrix 7102 . n - the number of submatrixes to be extracted 7103 . irow - index set of rows to extract 7104 . icol - index set of columns to extract 7105 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7106 7107 Output Parameter: 7108 . submat - the array of submatrices 7109 7110 Level: advanced 7111 7112 Note: 7113 This is used by `PCGASM` 7114 7115 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7116 @*/ 7117 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7118 { 7119 PetscInt i; 7120 PetscBool eq; 7121 7122 PetscFunctionBegin; 7123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7124 PetscValidType(mat, 1); 7125 if (n) { 7126 PetscAssertPointer(irow, 3); 7127 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7128 PetscAssertPointer(icol, 4); 7129 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7130 } 7131 PetscAssertPointer(submat, 6); 7132 if (n && scall == MAT_REUSE_MATRIX) { 7133 PetscAssertPointer(*submat, 6); 7134 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7135 } 7136 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7137 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7138 MatCheckPreallocated(mat, 1); 7139 7140 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7141 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7142 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7143 for (i = 0; i < n; i++) { 7144 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7145 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7146 } 7147 PetscFunctionReturn(PETSC_SUCCESS); 7148 } 7149 7150 /*@C 7151 MatDestroyMatrices - Destroys an array of matrices. 7152 7153 Collective 7154 7155 Input Parameters: 7156 + n - the number of local matrices 7157 - mat - the matrices (this is a pointer to the array of matrices) 7158 7159 Level: advanced 7160 7161 Note: 7162 Frees not only the matrices, but also the array that contains the matrices 7163 7164 Fortran Note: 7165 This does not free the array. 7166 7167 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7168 @*/ 7169 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7170 { 7171 PetscInt i; 7172 7173 PetscFunctionBegin; 7174 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7175 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7176 PetscAssertPointer(mat, 2); 7177 7178 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7179 7180 /* memory is allocated even if n = 0 */ 7181 PetscCall(PetscFree(*mat)); 7182 PetscFunctionReturn(PETSC_SUCCESS); 7183 } 7184 7185 /*@C 7186 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7187 7188 Collective 7189 7190 Input Parameters: 7191 + n - the number of local matrices 7192 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7193 sequence of `MatCreateSubMatrices()`) 7194 7195 Level: advanced 7196 7197 Note: 7198 Frees not only the matrices, but also the array that contains the matrices 7199 7200 Fortran Note: 7201 This does not free the array. 7202 7203 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7204 @*/ 7205 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7206 { 7207 Mat mat0; 7208 7209 PetscFunctionBegin; 7210 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7211 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7212 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7213 PetscAssertPointer(mat, 2); 7214 7215 mat0 = (*mat)[0]; 7216 if (mat0 && mat0->ops->destroysubmatrices) { 7217 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7218 } else { 7219 PetscCall(MatDestroyMatrices(n, mat)); 7220 } 7221 PetscFunctionReturn(PETSC_SUCCESS); 7222 } 7223 7224 /*@C 7225 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7226 7227 Collective 7228 7229 Input Parameter: 7230 . mat - the matrix 7231 7232 Output Parameter: 7233 . matstruct - the sequential matrix with the nonzero structure of mat 7234 7235 Level: developer 7236 7237 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7238 @*/ 7239 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7240 { 7241 PetscFunctionBegin; 7242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7243 PetscAssertPointer(matstruct, 2); 7244 7245 PetscValidType(mat, 1); 7246 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7247 MatCheckPreallocated(mat, 1); 7248 7249 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7250 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7251 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7252 PetscFunctionReturn(PETSC_SUCCESS); 7253 } 7254 7255 /*@C 7256 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7257 7258 Collective 7259 7260 Input Parameter: 7261 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7262 sequence of `MatGetSeqNonzeroStructure()`) 7263 7264 Level: advanced 7265 7266 Note: 7267 Frees not only the matrices, but also the array that contains the matrices 7268 7269 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7270 @*/ 7271 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7272 { 7273 PetscFunctionBegin; 7274 PetscAssertPointer(mat, 1); 7275 PetscCall(MatDestroy(mat)); 7276 PetscFunctionReturn(PETSC_SUCCESS); 7277 } 7278 7279 /*@ 7280 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7281 replaces the index sets by larger ones that represent submatrices with 7282 additional overlap. 7283 7284 Collective 7285 7286 Input Parameters: 7287 + mat - the matrix 7288 . n - the number of index sets 7289 . is - the array of index sets (these index sets will changed during the call) 7290 - ov - the additional overlap requested 7291 7292 Options Database Key: 7293 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7294 7295 Level: developer 7296 7297 Note: 7298 The computed overlap preserves the matrix block sizes when the blocks are square. 7299 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7300 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7301 7302 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7303 @*/ 7304 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7305 { 7306 PetscInt i, bs, cbs; 7307 7308 PetscFunctionBegin; 7309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7310 PetscValidType(mat, 1); 7311 PetscValidLogicalCollectiveInt(mat, n, 2); 7312 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7313 if (n) { 7314 PetscAssertPointer(is, 3); 7315 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7316 } 7317 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7318 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7319 MatCheckPreallocated(mat, 1); 7320 7321 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7322 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7323 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7324 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7325 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7326 if (bs == cbs) { 7327 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7328 } 7329 PetscFunctionReturn(PETSC_SUCCESS); 7330 } 7331 7332 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7333 7334 /*@ 7335 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7336 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7337 additional overlap. 7338 7339 Collective 7340 7341 Input Parameters: 7342 + mat - the matrix 7343 . n - the number of index sets 7344 . is - the array of index sets (these index sets will changed during the call) 7345 - ov - the additional overlap requested 7346 7347 ` Options Database Key: 7348 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7349 7350 Level: developer 7351 7352 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7353 @*/ 7354 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7355 { 7356 PetscInt i; 7357 7358 PetscFunctionBegin; 7359 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7360 PetscValidType(mat, 1); 7361 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7362 if (n) { 7363 PetscAssertPointer(is, 3); 7364 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7365 } 7366 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7367 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7368 MatCheckPreallocated(mat, 1); 7369 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7370 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7371 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7372 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7373 PetscFunctionReturn(PETSC_SUCCESS); 7374 } 7375 7376 /*@ 7377 MatGetBlockSize - Returns the matrix block size. 7378 7379 Not Collective 7380 7381 Input Parameter: 7382 . mat - the matrix 7383 7384 Output Parameter: 7385 . bs - block size 7386 7387 Level: intermediate 7388 7389 Notes: 7390 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7391 7392 If the block size has not been set yet this routine returns 1. 7393 7394 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7395 @*/ 7396 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7397 { 7398 PetscFunctionBegin; 7399 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7400 PetscAssertPointer(bs, 2); 7401 *bs = PetscAbs(mat->rmap->bs); 7402 PetscFunctionReturn(PETSC_SUCCESS); 7403 } 7404 7405 /*@ 7406 MatGetBlockSizes - Returns the matrix block row and column sizes. 7407 7408 Not Collective 7409 7410 Input Parameter: 7411 . mat - the matrix 7412 7413 Output Parameters: 7414 + rbs - row block size 7415 - cbs - column block size 7416 7417 Level: intermediate 7418 7419 Notes: 7420 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7421 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7422 7423 If a block size has not been set yet this routine returns 1. 7424 7425 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7426 @*/ 7427 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7428 { 7429 PetscFunctionBegin; 7430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7431 if (rbs) PetscAssertPointer(rbs, 2); 7432 if (cbs) PetscAssertPointer(cbs, 3); 7433 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7434 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7435 PetscFunctionReturn(PETSC_SUCCESS); 7436 } 7437 7438 /*@ 7439 MatSetBlockSize - Sets the matrix block size. 7440 7441 Logically Collective 7442 7443 Input Parameters: 7444 + mat - the matrix 7445 - bs - block size 7446 7447 Level: intermediate 7448 7449 Notes: 7450 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7451 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7452 7453 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7454 is compatible with the matrix local sizes. 7455 7456 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7457 @*/ 7458 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7459 { 7460 PetscFunctionBegin; 7461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7462 PetscValidLogicalCollectiveInt(mat, bs, 2); 7463 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7464 PetscFunctionReturn(PETSC_SUCCESS); 7465 } 7466 7467 typedef struct { 7468 PetscInt n; 7469 IS *is; 7470 Mat *mat; 7471 PetscObjectState nonzerostate; 7472 Mat C; 7473 } EnvelopeData; 7474 7475 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7476 { 7477 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7478 PetscCall(PetscFree(edata->is)); 7479 PetscCall(PetscFree(edata)); 7480 return PETSC_SUCCESS; 7481 } 7482 7483 /*@ 7484 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7485 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7486 7487 Collective 7488 7489 Input Parameter: 7490 . mat - the matrix 7491 7492 Level: intermediate 7493 7494 Notes: 7495 There can be zeros within the blocks 7496 7497 The blocks can overlap between processes, including laying on more than two processes 7498 7499 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7500 @*/ 7501 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7502 { 7503 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7504 PetscInt *diag, *odiag, sc; 7505 VecScatter scatter; 7506 PetscScalar *seqv; 7507 const PetscScalar *parv; 7508 const PetscInt *ia, *ja; 7509 PetscBool set, flag, done; 7510 Mat AA = mat, A; 7511 MPI_Comm comm; 7512 PetscMPIInt rank, size, tag; 7513 MPI_Status status; 7514 PetscContainer container; 7515 EnvelopeData *edata; 7516 Vec seq, par; 7517 IS isglobal; 7518 7519 PetscFunctionBegin; 7520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7521 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7522 if (!set || !flag) { 7523 /* TODO: only needs nonzero structure of transpose */ 7524 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7525 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7526 } 7527 PetscCall(MatAIJGetLocalMat(AA, &A)); 7528 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7529 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7530 7531 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7532 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7533 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7534 PetscCallMPI(MPI_Comm_size(comm, &size)); 7535 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7536 7537 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7538 7539 if (rank > 0) { 7540 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7541 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7542 } 7543 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7544 for (i = 0; i < n; i++) { 7545 env = PetscMax(env, ja[ia[i + 1] - 1]); 7546 II = rstart + i; 7547 if (env == II) { 7548 starts[lblocks] = tbs; 7549 sizes[lblocks++] = 1 + II - tbs; 7550 tbs = 1 + II; 7551 } 7552 } 7553 if (rank < size - 1) { 7554 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7555 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7556 } 7557 7558 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7559 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7560 PetscCall(MatDestroy(&A)); 7561 7562 PetscCall(PetscNew(&edata)); 7563 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7564 edata->n = lblocks; 7565 /* create IS needed for extracting blocks from the original matrix */ 7566 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7567 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7568 7569 /* Create the resulting inverse matrix structure with preallocation information */ 7570 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7571 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7572 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7573 PetscCall(MatSetType(edata->C, MATAIJ)); 7574 7575 /* Communicate the start and end of each row, from each block to the correct rank */ 7576 /* TODO: Use PetscSF instead of VecScatter */ 7577 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7578 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7579 PetscCall(VecGetArrayWrite(seq, &seqv)); 7580 for (PetscInt i = 0; i < lblocks; i++) { 7581 for (PetscInt j = 0; j < sizes[i]; j++) { 7582 seqv[cnt] = starts[i]; 7583 seqv[cnt + 1] = starts[i] + sizes[i]; 7584 cnt += 2; 7585 } 7586 } 7587 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7588 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7589 sc -= cnt; 7590 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7591 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7592 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7593 PetscCall(ISDestroy(&isglobal)); 7594 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7595 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7596 PetscCall(VecScatterDestroy(&scatter)); 7597 PetscCall(VecDestroy(&seq)); 7598 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7599 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7600 PetscCall(VecGetArrayRead(par, &parv)); 7601 cnt = 0; 7602 PetscCall(MatGetSize(mat, NULL, &n)); 7603 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7604 PetscInt start, end, d = 0, od = 0; 7605 7606 start = (PetscInt)PetscRealPart(parv[cnt]); 7607 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7608 cnt += 2; 7609 7610 if (start < cstart) { 7611 od += cstart - start + n - cend; 7612 d += cend - cstart; 7613 } else if (start < cend) { 7614 od += n - cend; 7615 d += cend - start; 7616 } else od += n - start; 7617 if (end <= cstart) { 7618 od -= cstart - end + n - cend; 7619 d -= cend - cstart; 7620 } else if (end < cend) { 7621 od -= n - cend; 7622 d -= cend - end; 7623 } else od -= n - end; 7624 7625 odiag[i] = od; 7626 diag[i] = d; 7627 } 7628 PetscCall(VecRestoreArrayRead(par, &parv)); 7629 PetscCall(VecDestroy(&par)); 7630 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7631 PetscCall(PetscFree2(diag, odiag)); 7632 PetscCall(PetscFree2(sizes, starts)); 7633 7634 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7635 PetscCall(PetscContainerSetPointer(container, edata)); 7636 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7637 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7638 PetscCall(PetscObjectDereference((PetscObject)container)); 7639 PetscFunctionReturn(PETSC_SUCCESS); 7640 } 7641 7642 /*@ 7643 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7644 7645 Collective 7646 7647 Input Parameters: 7648 + A - the matrix 7649 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7650 7651 Output Parameter: 7652 . C - matrix with inverted block diagonal of `A` 7653 7654 Level: advanced 7655 7656 Note: 7657 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7658 7659 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7660 @*/ 7661 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7662 { 7663 PetscContainer container; 7664 EnvelopeData *edata; 7665 PetscObjectState nonzerostate; 7666 7667 PetscFunctionBegin; 7668 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7669 if (!container) { 7670 PetscCall(MatComputeVariableBlockEnvelope(A)); 7671 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7672 } 7673 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7674 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7675 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7676 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7677 7678 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7679 *C = edata->C; 7680 7681 for (PetscInt i = 0; i < edata->n; i++) { 7682 Mat D; 7683 PetscScalar *dvalues; 7684 7685 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7686 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7687 PetscCall(MatSeqDenseInvert(D)); 7688 PetscCall(MatDenseGetArray(D, &dvalues)); 7689 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7690 PetscCall(MatDestroy(&D)); 7691 } 7692 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7693 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7694 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7695 PetscFunctionReturn(PETSC_SUCCESS); 7696 } 7697 7698 /*@ 7699 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7700 7701 Logically Collective 7702 7703 Input Parameters: 7704 + mat - the matrix 7705 . nblocks - the number of blocks on this process, each block can only exist on a single process 7706 - bsizes - the block sizes 7707 7708 Level: intermediate 7709 7710 Notes: 7711 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7712 7713 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. 7714 7715 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7716 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7717 @*/ 7718 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7719 { 7720 PetscInt i, ncnt = 0, nlocal; 7721 7722 PetscFunctionBegin; 7723 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7724 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7725 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7726 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7727 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); 7728 PetscCall(PetscFree(mat->bsizes)); 7729 mat->nblocks = nblocks; 7730 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7731 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7732 PetscFunctionReturn(PETSC_SUCCESS); 7733 } 7734 7735 /*@C 7736 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7737 7738 Logically Collective; No Fortran Support 7739 7740 Input Parameter: 7741 . mat - the matrix 7742 7743 Output Parameters: 7744 + nblocks - the number of blocks on this process 7745 - bsizes - the block sizes 7746 7747 Level: intermediate 7748 7749 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7750 @*/ 7751 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7752 { 7753 PetscFunctionBegin; 7754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7755 *nblocks = mat->nblocks; 7756 *bsizes = mat->bsizes; 7757 PetscFunctionReturn(PETSC_SUCCESS); 7758 } 7759 7760 /*@ 7761 MatSetBlockSizes - Sets the matrix block row and column sizes. 7762 7763 Logically Collective 7764 7765 Input Parameters: 7766 + mat - the matrix 7767 . rbs - row block size 7768 - cbs - column block size 7769 7770 Level: intermediate 7771 7772 Notes: 7773 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7774 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7775 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7776 7777 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7778 are compatible with the matrix local sizes. 7779 7780 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7781 7782 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7783 @*/ 7784 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7785 { 7786 PetscFunctionBegin; 7787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7788 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7789 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7790 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7791 if (mat->rmap->refcnt) { 7792 ISLocalToGlobalMapping l2g = NULL; 7793 PetscLayout nmap = NULL; 7794 7795 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7796 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7797 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7798 mat->rmap = nmap; 7799 mat->rmap->mapping = l2g; 7800 } 7801 if (mat->cmap->refcnt) { 7802 ISLocalToGlobalMapping l2g = NULL; 7803 PetscLayout nmap = NULL; 7804 7805 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7806 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7807 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7808 mat->cmap = nmap; 7809 mat->cmap->mapping = l2g; 7810 } 7811 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7812 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7813 PetscFunctionReturn(PETSC_SUCCESS); 7814 } 7815 7816 /*@ 7817 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7818 7819 Logically Collective 7820 7821 Input Parameters: 7822 + mat - the matrix 7823 . fromRow - matrix from which to copy row block size 7824 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7825 7826 Level: developer 7827 7828 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7829 @*/ 7830 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7831 { 7832 PetscFunctionBegin; 7833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7834 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7835 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7836 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7837 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7838 PetscFunctionReturn(PETSC_SUCCESS); 7839 } 7840 7841 /*@ 7842 MatResidual - Default routine to calculate the residual r = b - Ax 7843 7844 Collective 7845 7846 Input Parameters: 7847 + mat - the matrix 7848 . b - the right-hand-side 7849 - x - the approximate solution 7850 7851 Output Parameter: 7852 . r - location to store the residual 7853 7854 Level: developer 7855 7856 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7857 @*/ 7858 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7859 { 7860 PetscFunctionBegin; 7861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7862 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7863 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7864 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7865 PetscValidType(mat, 1); 7866 MatCheckPreallocated(mat, 1); 7867 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7868 if (!mat->ops->residual) { 7869 PetscCall(MatMult(mat, x, r)); 7870 PetscCall(VecAYPX(r, -1.0, b)); 7871 } else { 7872 PetscUseTypeMethod(mat, residual, b, x, r); 7873 } 7874 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7875 PetscFunctionReturn(PETSC_SUCCESS); 7876 } 7877 7878 /*MC 7879 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7880 7881 Synopsis: 7882 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7883 7884 Not Collective 7885 7886 Input Parameters: 7887 + A - the matrix 7888 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7889 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7890 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7891 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7892 always used. 7893 7894 Output Parameters: 7895 + n - number of local rows in the (possibly compressed) matrix 7896 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7897 . ja - the column indices 7898 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7899 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7900 7901 Level: developer 7902 7903 Note: 7904 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7905 7906 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7907 M*/ 7908 7909 /*MC 7910 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7911 7912 Synopsis: 7913 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7914 7915 Not Collective 7916 7917 Input Parameters: 7918 + A - the matrix 7919 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7920 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7921 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7922 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7923 always used. 7924 . n - number of local rows in the (possibly compressed) matrix 7925 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7926 . ja - the column indices 7927 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7928 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7929 7930 Level: developer 7931 7932 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7933 M*/ 7934 7935 /*@C 7936 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7937 7938 Collective 7939 7940 Input Parameters: 7941 + mat - 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, use `NULL` if not needed 7950 . 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 7951 . ja - the column indices, use `NULL` if not needed 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 Notes: 7958 You CANNOT change any of the ia[] or ja[] values. 7959 7960 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7961 7962 Fortran Notes: 7963 Use 7964 .vb 7965 PetscInt, pointer :: ia(:),ja(:) 7966 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7967 ! Access the ith and jth entries via ia(i) and ja(j) 7968 .ve 7969 7970 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7971 7972 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7973 @*/ 7974 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7975 { 7976 PetscFunctionBegin; 7977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7978 PetscValidType(mat, 1); 7979 if (n) PetscAssertPointer(n, 5); 7980 if (ia) PetscAssertPointer(ia, 6); 7981 if (ja) PetscAssertPointer(ja, 7); 7982 if (done) PetscAssertPointer(done, 8); 7983 MatCheckPreallocated(mat, 1); 7984 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7985 else { 7986 if (done) *done = PETSC_TRUE; 7987 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7988 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7989 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7990 } 7991 PetscFunctionReturn(PETSC_SUCCESS); 7992 } 7993 7994 /*@C 7995 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7996 7997 Collective 7998 7999 Input Parameters: 8000 + mat - the matrix 8001 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8002 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8003 symmetrized 8004 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8005 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8006 always used. 8007 . n - number of columns in the (possibly compressed) matrix 8008 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8009 - ja - the row indices 8010 8011 Output Parameter: 8012 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8013 8014 Level: developer 8015 8016 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8017 @*/ 8018 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8019 { 8020 PetscFunctionBegin; 8021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8022 PetscValidType(mat, 1); 8023 PetscAssertPointer(n, 5); 8024 if (ia) PetscAssertPointer(ia, 6); 8025 if (ja) PetscAssertPointer(ja, 7); 8026 PetscAssertPointer(done, 8); 8027 MatCheckPreallocated(mat, 1); 8028 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8029 else { 8030 *done = PETSC_TRUE; 8031 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8032 } 8033 PetscFunctionReturn(PETSC_SUCCESS); 8034 } 8035 8036 /*@C 8037 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8038 8039 Collective 8040 8041 Input Parameters: 8042 + mat - the matrix 8043 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8044 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8045 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8046 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8047 always used. 8048 . n - size of (possibly compressed) matrix 8049 . ia - the row pointers 8050 - ja - the column indices 8051 8052 Output Parameter: 8053 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8054 8055 Level: developer 8056 8057 Note: 8058 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8059 us of the array after it has been restored. If you pass `NULL`, it will 8060 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8061 8062 Fortran Note: 8063 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8064 8065 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8066 @*/ 8067 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8068 { 8069 PetscFunctionBegin; 8070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8071 PetscValidType(mat, 1); 8072 if (ia) PetscAssertPointer(ia, 6); 8073 if (ja) PetscAssertPointer(ja, 7); 8074 if (done) PetscAssertPointer(done, 8); 8075 MatCheckPreallocated(mat, 1); 8076 8077 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8078 else { 8079 if (done) *done = PETSC_TRUE; 8080 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8081 if (n) *n = 0; 8082 if (ia) *ia = NULL; 8083 if (ja) *ja = NULL; 8084 } 8085 PetscFunctionReturn(PETSC_SUCCESS); 8086 } 8087 8088 /*@C 8089 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8090 8091 Collective 8092 8093 Input Parameters: 8094 + mat - the matrix 8095 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8096 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8097 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8098 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8099 always used. 8100 8101 Output Parameters: 8102 + n - size of (possibly compressed) matrix 8103 . ia - the column pointers 8104 . ja - the row indices 8105 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8106 8107 Level: developer 8108 8109 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8110 @*/ 8111 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8112 { 8113 PetscFunctionBegin; 8114 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8115 PetscValidType(mat, 1); 8116 if (ia) PetscAssertPointer(ia, 6); 8117 if (ja) PetscAssertPointer(ja, 7); 8118 PetscAssertPointer(done, 8); 8119 MatCheckPreallocated(mat, 1); 8120 8121 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8122 else { 8123 *done = PETSC_TRUE; 8124 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8125 if (n) *n = 0; 8126 if (ia) *ia = NULL; 8127 if (ja) *ja = NULL; 8128 } 8129 PetscFunctionReturn(PETSC_SUCCESS); 8130 } 8131 8132 /*@C 8133 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8134 `MatGetColumnIJ()`. 8135 8136 Collective 8137 8138 Input Parameters: 8139 + mat - the matrix 8140 . ncolors - maximum color value 8141 . n - number of entries in colorarray 8142 - colorarray - array indicating color for each column 8143 8144 Output Parameter: 8145 . iscoloring - coloring generated using colorarray information 8146 8147 Level: developer 8148 8149 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8150 @*/ 8151 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8152 { 8153 PetscFunctionBegin; 8154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8155 PetscValidType(mat, 1); 8156 PetscAssertPointer(colorarray, 4); 8157 PetscAssertPointer(iscoloring, 5); 8158 MatCheckPreallocated(mat, 1); 8159 8160 if (!mat->ops->coloringpatch) { 8161 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8162 } else { 8163 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8164 } 8165 PetscFunctionReturn(PETSC_SUCCESS); 8166 } 8167 8168 /*@ 8169 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8170 8171 Logically Collective 8172 8173 Input Parameter: 8174 . mat - the factored matrix to be reset 8175 8176 Level: developer 8177 8178 Notes: 8179 This routine should be used only with factored matrices formed by in-place 8180 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8181 format). This option can save memory, for example, when solving nonlinear 8182 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8183 ILU(0) preconditioner. 8184 8185 One can specify in-place ILU(0) factorization by calling 8186 .vb 8187 PCType(pc,PCILU); 8188 PCFactorSeUseInPlace(pc); 8189 .ve 8190 or by using the options -pc_type ilu -pc_factor_in_place 8191 8192 In-place factorization ILU(0) can also be used as a local 8193 solver for the blocks within the block Jacobi or additive Schwarz 8194 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8195 for details on setting local solver options. 8196 8197 Most users should employ the `KSP` interface for linear solvers 8198 instead of working directly with matrix algebra routines such as this. 8199 See, e.g., `KSPCreate()`. 8200 8201 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8202 @*/ 8203 PetscErrorCode MatSetUnfactored(Mat mat) 8204 { 8205 PetscFunctionBegin; 8206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8207 PetscValidType(mat, 1); 8208 MatCheckPreallocated(mat, 1); 8209 mat->factortype = MAT_FACTOR_NONE; 8210 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8211 PetscUseTypeMethod(mat, setunfactored); 8212 PetscFunctionReturn(PETSC_SUCCESS); 8213 } 8214 8215 /*MC 8216 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8217 8218 Synopsis: 8219 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8220 8221 Not Collective 8222 8223 Input Parameter: 8224 . x - matrix 8225 8226 Output Parameters: 8227 + xx_v - the Fortran pointer to the array 8228 - ierr - error code 8229 8230 Example of Usage: 8231 .vb 8232 PetscScalar, pointer xx_v(:,:) 8233 .... 8234 call MatDenseGetArrayF90(x,xx_v,ierr) 8235 a = xx_v(3) 8236 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8237 .ve 8238 8239 Level: advanced 8240 8241 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8242 M*/ 8243 8244 /*MC 8245 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8246 accessed with `MatDenseGetArrayF90()`. 8247 8248 Synopsis: 8249 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8250 8251 Not Collective 8252 8253 Input Parameters: 8254 + x - matrix 8255 - xx_v - the Fortran90 pointer to the array 8256 8257 Output Parameter: 8258 . ierr - error code 8259 8260 Example of Usage: 8261 .vb 8262 PetscScalar, pointer xx_v(:,:) 8263 .... 8264 call MatDenseGetArrayF90(x,xx_v,ierr) 8265 a = xx_v(3) 8266 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8267 .ve 8268 8269 Level: advanced 8270 8271 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8272 M*/ 8273 8274 /*MC 8275 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8276 8277 Synopsis: 8278 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8279 8280 Not Collective 8281 8282 Input Parameter: 8283 . x - matrix 8284 8285 Output Parameters: 8286 + xx_v - the Fortran pointer to the array 8287 - ierr - error code 8288 8289 Example of Usage: 8290 .vb 8291 PetscScalar, pointer xx_v(:) 8292 .... 8293 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8294 a = xx_v(3) 8295 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8296 .ve 8297 8298 Level: advanced 8299 8300 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8301 M*/ 8302 8303 /*MC 8304 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8305 accessed with `MatSeqAIJGetArrayF90()`. 8306 8307 Synopsis: 8308 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8309 8310 Not Collective 8311 8312 Input Parameters: 8313 + x - matrix 8314 - xx_v - the Fortran90 pointer to the array 8315 8316 Output Parameter: 8317 . ierr - error code 8318 8319 Example of Usage: 8320 .vb 8321 PetscScalar, pointer xx_v(:) 8322 .... 8323 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8324 a = xx_v(3) 8325 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8326 .ve 8327 8328 Level: advanced 8329 8330 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8331 M*/ 8332 8333 /*@ 8334 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8335 as the original matrix. 8336 8337 Collective 8338 8339 Input Parameters: 8340 + mat - the original matrix 8341 . isrow - parallel `IS` containing the rows this processor should obtain 8342 . 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. 8343 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8344 8345 Output Parameter: 8346 . newmat - the new submatrix, of the same type as the original matrix 8347 8348 Level: advanced 8349 8350 Notes: 8351 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8352 8353 Some matrix types place restrictions on the row and column indices, such 8354 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; 8355 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8356 8357 The index sets may not have duplicate entries. 8358 8359 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8360 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8361 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8362 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8363 you are finished using it. 8364 8365 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8366 the input matrix. 8367 8368 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8369 8370 If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature 8371 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8372 8373 Example usage: 8374 Consider the following 8x8 matrix with 34 non-zero values, that is 8375 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8376 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8377 as follows 8378 .vb 8379 1 2 0 | 0 3 0 | 0 4 8380 Proc0 0 5 6 | 7 0 0 | 8 0 8381 9 0 10 | 11 0 0 | 12 0 8382 ------------------------------------- 8383 13 0 14 | 15 16 17 | 0 0 8384 Proc1 0 18 0 | 19 20 21 | 0 0 8385 0 0 0 | 22 23 0 | 24 0 8386 ------------------------------------- 8387 Proc2 25 26 27 | 0 0 28 | 29 0 8388 30 0 0 | 31 32 33 | 0 34 8389 .ve 8390 8391 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8392 8393 .vb 8394 2 0 | 0 3 0 | 0 8395 Proc0 5 6 | 7 0 0 | 8 8396 ------------------------------- 8397 Proc1 18 0 | 19 20 21 | 0 8398 ------------------------------- 8399 Proc2 26 27 | 0 0 28 | 29 8400 0 0 | 31 32 33 | 0 8401 .ve 8402 8403 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8404 @*/ 8405 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8406 { 8407 PetscMPIInt size; 8408 Mat *local; 8409 IS iscoltmp; 8410 PetscBool flg; 8411 8412 PetscFunctionBegin; 8413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8414 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8415 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8416 PetscAssertPointer(newmat, 5); 8417 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8418 PetscValidType(mat, 1); 8419 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8420 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8421 8422 MatCheckPreallocated(mat, 1); 8423 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8424 8425 if (!iscol || isrow == iscol) { 8426 PetscBool stride; 8427 PetscMPIInt grabentirematrix = 0, grab; 8428 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8429 if (stride) { 8430 PetscInt first, step, n, rstart, rend; 8431 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8432 if (step == 1) { 8433 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8434 if (rstart == first) { 8435 PetscCall(ISGetLocalSize(isrow, &n)); 8436 if (n == rend - rstart) grabentirematrix = 1; 8437 } 8438 } 8439 } 8440 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8441 if (grab) { 8442 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8443 if (cll == MAT_INITIAL_MATRIX) { 8444 *newmat = mat; 8445 PetscCall(PetscObjectReference((PetscObject)mat)); 8446 } 8447 PetscFunctionReturn(PETSC_SUCCESS); 8448 } 8449 } 8450 8451 if (!iscol) { 8452 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8453 } else { 8454 iscoltmp = iscol; 8455 } 8456 8457 /* if original matrix is on just one processor then use submatrix generated */ 8458 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8459 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8460 goto setproperties; 8461 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8462 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8463 *newmat = *local; 8464 PetscCall(PetscFree(local)); 8465 goto setproperties; 8466 } else if (!mat->ops->createsubmatrix) { 8467 /* Create a new matrix type that implements the operation using the full matrix */ 8468 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8469 switch (cll) { 8470 case MAT_INITIAL_MATRIX: 8471 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8472 break; 8473 case MAT_REUSE_MATRIX: 8474 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8475 break; 8476 default: 8477 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8478 } 8479 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8480 goto setproperties; 8481 } 8482 8483 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8484 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8485 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8486 8487 setproperties: 8488 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8489 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8490 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8491 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8492 PetscFunctionReturn(PETSC_SUCCESS); 8493 } 8494 8495 /*@ 8496 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8497 8498 Not Collective 8499 8500 Input Parameters: 8501 + A - the matrix we wish to propagate options from 8502 - B - the matrix we wish to propagate options to 8503 8504 Level: beginner 8505 8506 Note: 8507 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8508 8509 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8510 @*/ 8511 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8512 { 8513 PetscFunctionBegin; 8514 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8515 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8516 B->symmetry_eternal = A->symmetry_eternal; 8517 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8518 B->symmetric = A->symmetric; 8519 B->structurally_symmetric = A->structurally_symmetric; 8520 B->spd = A->spd; 8521 B->hermitian = A->hermitian; 8522 PetscFunctionReturn(PETSC_SUCCESS); 8523 } 8524 8525 /*@ 8526 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8527 used during the assembly process to store values that belong to 8528 other processors. 8529 8530 Not Collective 8531 8532 Input Parameters: 8533 + mat - the matrix 8534 . size - the initial size of the stash. 8535 - bsize - the initial size of the block-stash(if used). 8536 8537 Options Database Keys: 8538 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8539 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8540 8541 Level: intermediate 8542 8543 Notes: 8544 The block-stash is used for values set with `MatSetValuesBlocked()` while 8545 the stash is used for values set with `MatSetValues()` 8546 8547 Run with the option -info and look for output of the form 8548 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8549 to determine the appropriate value, MM, to use for size and 8550 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8551 to determine the value, BMM to use for bsize 8552 8553 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8554 @*/ 8555 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8556 { 8557 PetscFunctionBegin; 8558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8559 PetscValidType(mat, 1); 8560 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8561 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8562 PetscFunctionReturn(PETSC_SUCCESS); 8563 } 8564 8565 /*@ 8566 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8567 the matrix 8568 8569 Neighbor-wise Collective 8570 8571 Input Parameters: 8572 + A - the matrix 8573 . x - the vector to be multiplied by the interpolation operator 8574 - y - the vector to be added to the result 8575 8576 Output Parameter: 8577 . w - the resulting vector 8578 8579 Level: intermediate 8580 8581 Notes: 8582 `w` may be the same vector as `y`. 8583 8584 This allows one to use either the restriction or interpolation (its transpose) 8585 matrix to do the interpolation 8586 8587 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8588 @*/ 8589 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8590 { 8591 PetscInt M, N, Ny; 8592 8593 PetscFunctionBegin; 8594 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8595 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8596 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8597 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8598 PetscCall(MatGetSize(A, &M, &N)); 8599 PetscCall(VecGetSize(y, &Ny)); 8600 if (M == Ny) { 8601 PetscCall(MatMultAdd(A, x, y, w)); 8602 } else { 8603 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8604 } 8605 PetscFunctionReturn(PETSC_SUCCESS); 8606 } 8607 8608 /*@ 8609 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8610 the matrix 8611 8612 Neighbor-wise Collective 8613 8614 Input Parameters: 8615 + A - the matrix 8616 - x - the vector to be interpolated 8617 8618 Output Parameter: 8619 . y - the resulting vector 8620 8621 Level: intermediate 8622 8623 Note: 8624 This allows one to use either the restriction or interpolation (its transpose) 8625 matrix to do the interpolation 8626 8627 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8628 @*/ 8629 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8630 { 8631 PetscInt M, N, Ny; 8632 8633 PetscFunctionBegin; 8634 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8635 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8636 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8637 PetscCall(MatGetSize(A, &M, &N)); 8638 PetscCall(VecGetSize(y, &Ny)); 8639 if (M == Ny) { 8640 PetscCall(MatMult(A, x, y)); 8641 } else { 8642 PetscCall(MatMultTranspose(A, x, y)); 8643 } 8644 PetscFunctionReturn(PETSC_SUCCESS); 8645 } 8646 8647 /*@ 8648 MatRestrict - $y = A*x$ or $A^T*x$ 8649 8650 Neighbor-wise Collective 8651 8652 Input Parameters: 8653 + A - the matrix 8654 - x - the vector to be restricted 8655 8656 Output Parameter: 8657 . y - the resulting vector 8658 8659 Level: intermediate 8660 8661 Note: 8662 This allows one to use either the restriction or interpolation (its transpose) 8663 matrix to do the restriction 8664 8665 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8666 @*/ 8667 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8668 { 8669 PetscInt M, N, Ny; 8670 8671 PetscFunctionBegin; 8672 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8673 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8674 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8675 PetscCall(MatGetSize(A, &M, &N)); 8676 PetscCall(VecGetSize(y, &Ny)); 8677 if (M == Ny) { 8678 PetscCall(MatMult(A, x, y)); 8679 } else { 8680 PetscCall(MatMultTranspose(A, x, y)); 8681 } 8682 PetscFunctionReturn(PETSC_SUCCESS); 8683 } 8684 8685 /*@ 8686 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8687 8688 Neighbor-wise Collective 8689 8690 Input Parameters: 8691 + A - the matrix 8692 . x - the input dense matrix to be multiplied 8693 - w - the input dense matrix to be added to the result 8694 8695 Output Parameter: 8696 . y - the output dense matrix 8697 8698 Level: intermediate 8699 8700 Note: 8701 This allows one to use either the restriction or interpolation (its transpose) 8702 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8703 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8704 8705 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8706 @*/ 8707 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8708 { 8709 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8710 PetscBool trans = PETSC_TRUE; 8711 MatReuse reuse = MAT_INITIAL_MATRIX; 8712 8713 PetscFunctionBegin; 8714 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8715 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8716 PetscValidType(x, 2); 8717 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8718 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8719 PetscCall(MatGetSize(A, &M, &N)); 8720 PetscCall(MatGetSize(x, &Mx, &Nx)); 8721 if (N == Mx) trans = PETSC_FALSE; 8722 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); 8723 Mo = trans ? N : M; 8724 if (*y) { 8725 PetscCall(MatGetSize(*y, &My, &Ny)); 8726 if (Mo == My && Nx == Ny) { 8727 reuse = MAT_REUSE_MATRIX; 8728 } else { 8729 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); 8730 PetscCall(MatDestroy(y)); 8731 } 8732 } 8733 8734 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8735 PetscBool flg; 8736 8737 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8738 if (w) { 8739 PetscInt My, Ny, Mw, Nw; 8740 8741 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8742 PetscCall(MatGetSize(*y, &My, &Ny)); 8743 PetscCall(MatGetSize(w, &Mw, &Nw)); 8744 if (!flg || My != Mw || Ny != Nw) w = NULL; 8745 } 8746 if (!w) { 8747 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8748 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8749 PetscCall(PetscObjectDereference((PetscObject)w)); 8750 } else { 8751 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8752 } 8753 } 8754 if (!trans) { 8755 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8756 } else { 8757 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8758 } 8759 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8760 PetscFunctionReturn(PETSC_SUCCESS); 8761 } 8762 8763 /*@ 8764 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8765 8766 Neighbor-wise Collective 8767 8768 Input Parameters: 8769 + A - the matrix 8770 - x - the input dense matrix 8771 8772 Output Parameter: 8773 . y - the output dense matrix 8774 8775 Level: intermediate 8776 8777 Note: 8778 This allows one to use either the restriction or interpolation (its transpose) 8779 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8780 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8781 8782 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8783 @*/ 8784 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8785 { 8786 PetscFunctionBegin; 8787 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8788 PetscFunctionReturn(PETSC_SUCCESS); 8789 } 8790 8791 /*@ 8792 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8793 8794 Neighbor-wise Collective 8795 8796 Input Parameters: 8797 + A - the matrix 8798 - x - the input dense matrix 8799 8800 Output Parameter: 8801 . y - the output dense matrix 8802 8803 Level: intermediate 8804 8805 Note: 8806 This allows one to use either the restriction or interpolation (its transpose) 8807 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8808 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8809 8810 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8811 @*/ 8812 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8813 { 8814 PetscFunctionBegin; 8815 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8816 PetscFunctionReturn(PETSC_SUCCESS); 8817 } 8818 8819 /*@ 8820 MatGetNullSpace - retrieves the null space of a matrix. 8821 8822 Logically Collective 8823 8824 Input Parameters: 8825 + mat - the matrix 8826 - nullsp - the null space object 8827 8828 Level: developer 8829 8830 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8831 @*/ 8832 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8833 { 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8836 PetscAssertPointer(nullsp, 2); 8837 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8838 PetscFunctionReturn(PETSC_SUCCESS); 8839 } 8840 8841 /*@ 8842 MatSetNullSpace - attaches a null space to a matrix. 8843 8844 Logically Collective 8845 8846 Input Parameters: 8847 + mat - the matrix 8848 - nullsp - the null space object 8849 8850 Level: advanced 8851 8852 Notes: 8853 This null space is used by the `KSP` linear solvers to solve singular systems. 8854 8855 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` 8856 8857 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 8858 to zero but the linear system will still be solved in a least squares sense. 8859 8860 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8861 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)$. 8862 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 8863 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 8864 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$). 8865 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8866 8867 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8868 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8869 routine also automatically calls `MatSetTransposeNullSpace()`. 8870 8871 The user should call `MatNullSpaceDestroy()`. 8872 8873 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8874 `KSPSetPCSide()` 8875 @*/ 8876 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8877 { 8878 PetscFunctionBegin; 8879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8880 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8881 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8882 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8883 mat->nullsp = nullsp; 8884 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8885 PetscFunctionReturn(PETSC_SUCCESS); 8886 } 8887 8888 /*@ 8889 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8890 8891 Logically Collective 8892 8893 Input Parameters: 8894 + mat - the matrix 8895 - nullsp - the null space object 8896 8897 Level: developer 8898 8899 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8900 @*/ 8901 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8902 { 8903 PetscFunctionBegin; 8904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8905 PetscValidType(mat, 1); 8906 PetscAssertPointer(nullsp, 2); 8907 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8908 PetscFunctionReturn(PETSC_SUCCESS); 8909 } 8910 8911 /*@ 8912 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8913 8914 Logically Collective 8915 8916 Input Parameters: 8917 + mat - the matrix 8918 - nullsp - the null space object 8919 8920 Level: advanced 8921 8922 Notes: 8923 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8924 8925 See `MatSetNullSpace()` 8926 8927 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8928 @*/ 8929 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8930 { 8931 PetscFunctionBegin; 8932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8933 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8934 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8935 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8936 mat->transnullsp = nullsp; 8937 PetscFunctionReturn(PETSC_SUCCESS); 8938 } 8939 8940 /*@ 8941 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8942 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8943 8944 Logically Collective 8945 8946 Input Parameters: 8947 + mat - the matrix 8948 - nullsp - the null space object 8949 8950 Level: advanced 8951 8952 Notes: 8953 Overwrites any previous near null space that may have been attached 8954 8955 You can remove the null space by calling this routine with an `nullsp` of `NULL` 8956 8957 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8958 @*/ 8959 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8960 { 8961 PetscFunctionBegin; 8962 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8963 PetscValidType(mat, 1); 8964 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8965 MatCheckPreallocated(mat, 1); 8966 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8967 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8968 mat->nearnullsp = nullsp; 8969 PetscFunctionReturn(PETSC_SUCCESS); 8970 } 8971 8972 /*@ 8973 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8974 8975 Not Collective 8976 8977 Input Parameter: 8978 . mat - the matrix 8979 8980 Output Parameter: 8981 . nullsp - the null space object, `NULL` if not set 8982 8983 Level: advanced 8984 8985 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8986 @*/ 8987 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8988 { 8989 PetscFunctionBegin; 8990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8991 PetscValidType(mat, 1); 8992 PetscAssertPointer(nullsp, 2); 8993 MatCheckPreallocated(mat, 1); 8994 *nullsp = mat->nearnullsp; 8995 PetscFunctionReturn(PETSC_SUCCESS); 8996 } 8997 8998 /*@C 8999 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9000 9001 Collective 9002 9003 Input Parameters: 9004 + mat - the matrix 9005 . row - row/column permutation 9006 - info - information on desired factorization process 9007 9008 Level: developer 9009 9010 Notes: 9011 Probably really in-place only when level of fill is zero, otherwise allocates 9012 new space to store factored matrix and deletes previous memory. 9013 9014 Most users should employ the `KSP` interface for linear solvers 9015 instead of working directly with matrix algebra routines such as this. 9016 See, e.g., `KSPCreate()`. 9017 9018 Developer Note: 9019 The Fortran interface is not autogenerated as the 9020 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9021 9022 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9023 @*/ 9024 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9025 { 9026 PetscFunctionBegin; 9027 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9028 PetscValidType(mat, 1); 9029 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9030 PetscAssertPointer(info, 3); 9031 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9032 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9033 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9034 MatCheckPreallocated(mat, 1); 9035 PetscUseTypeMethod(mat, iccfactor, row, info); 9036 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9037 PetscFunctionReturn(PETSC_SUCCESS); 9038 } 9039 9040 /*@ 9041 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9042 ghosted ones. 9043 9044 Not Collective 9045 9046 Input Parameters: 9047 + mat - the matrix 9048 - diag - the diagonal values, including ghost ones 9049 9050 Level: developer 9051 9052 Notes: 9053 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9054 9055 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9056 9057 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9058 @*/ 9059 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9060 { 9061 PetscMPIInt size; 9062 9063 PetscFunctionBegin; 9064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9065 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9066 PetscValidType(mat, 1); 9067 9068 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9069 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9070 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9071 if (size == 1) { 9072 PetscInt n, m; 9073 PetscCall(VecGetSize(diag, &n)); 9074 PetscCall(MatGetSize(mat, NULL, &m)); 9075 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9076 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9077 } else { 9078 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9079 } 9080 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9081 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9082 PetscFunctionReturn(PETSC_SUCCESS); 9083 } 9084 9085 /*@ 9086 MatGetInertia - Gets the inertia from a factored matrix 9087 9088 Collective 9089 9090 Input Parameter: 9091 . mat - the matrix 9092 9093 Output Parameters: 9094 + nneg - number of negative eigenvalues 9095 . nzero - number of zero eigenvalues 9096 - npos - number of positive eigenvalues 9097 9098 Level: advanced 9099 9100 Note: 9101 Matrix must have been factored by `MatCholeskyFactor()` 9102 9103 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9104 @*/ 9105 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9106 { 9107 PetscFunctionBegin; 9108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9109 PetscValidType(mat, 1); 9110 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9112 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9113 PetscFunctionReturn(PETSC_SUCCESS); 9114 } 9115 9116 /*@C 9117 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9118 9119 Neighbor-wise Collective 9120 9121 Input Parameters: 9122 + mat - the factored matrix obtained with `MatGetFactor()` 9123 - b - the right-hand-side vectors 9124 9125 Output Parameter: 9126 . x - the result vectors 9127 9128 Level: developer 9129 9130 Note: 9131 The vectors `b` and `x` cannot be the same. I.e., one cannot 9132 call `MatSolves`(A,x,x). 9133 9134 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9135 @*/ 9136 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9137 { 9138 PetscFunctionBegin; 9139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9140 PetscValidType(mat, 1); 9141 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9142 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9143 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9144 9145 MatCheckPreallocated(mat, 1); 9146 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9147 PetscUseTypeMethod(mat, solves, b, x); 9148 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9149 PetscFunctionReturn(PETSC_SUCCESS); 9150 } 9151 9152 /*@ 9153 MatIsSymmetric - Test whether a matrix is symmetric 9154 9155 Collective 9156 9157 Input Parameters: 9158 + A - the matrix to test 9159 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9160 9161 Output Parameter: 9162 . flg - the result 9163 9164 Level: intermediate 9165 9166 Notes: 9167 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9168 9169 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9170 9171 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9172 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9173 9174 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9175 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9176 @*/ 9177 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9178 { 9179 PetscFunctionBegin; 9180 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9181 PetscAssertPointer(flg, 3); 9182 9183 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9184 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9185 else { 9186 PetscUseTypeMethod(A, issymmetric, tol, flg); 9187 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9188 } 9189 PetscFunctionReturn(PETSC_SUCCESS); 9190 } 9191 9192 /*@ 9193 MatIsHermitian - Test whether a matrix is Hermitian 9194 9195 Collective 9196 9197 Input Parameters: 9198 + A - the matrix to test 9199 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9200 9201 Output Parameter: 9202 . flg - the result 9203 9204 Level: intermediate 9205 9206 Notes: 9207 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9208 9209 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9210 9211 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9212 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9213 9214 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9215 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9216 @*/ 9217 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9218 { 9219 PetscFunctionBegin; 9220 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9221 PetscAssertPointer(flg, 3); 9222 9223 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9224 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9225 else { 9226 PetscUseTypeMethod(A, ishermitian, tol, flg); 9227 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9228 } 9229 PetscFunctionReturn(PETSC_SUCCESS); 9230 } 9231 9232 /*@ 9233 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9234 9235 Not Collective 9236 9237 Input Parameter: 9238 . A - the matrix to check 9239 9240 Output Parameters: 9241 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9242 - flg - the result (only valid if set is `PETSC_TRUE`) 9243 9244 Level: advanced 9245 9246 Notes: 9247 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9248 if you want it explicitly checked 9249 9250 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9251 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9252 9253 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9254 @*/ 9255 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9256 { 9257 PetscFunctionBegin; 9258 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9259 PetscAssertPointer(set, 2); 9260 PetscAssertPointer(flg, 3); 9261 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9262 *set = PETSC_TRUE; 9263 *flg = PetscBool3ToBool(A->symmetric); 9264 } else { 9265 *set = PETSC_FALSE; 9266 } 9267 PetscFunctionReturn(PETSC_SUCCESS); 9268 } 9269 9270 /*@ 9271 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9272 9273 Not Collective 9274 9275 Input Parameter: 9276 . A - the matrix to check 9277 9278 Output Parameters: 9279 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9280 - flg - the result (only valid if set is `PETSC_TRUE`) 9281 9282 Level: advanced 9283 9284 Notes: 9285 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9286 9287 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9288 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9289 9290 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9291 @*/ 9292 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9293 { 9294 PetscFunctionBegin; 9295 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9296 PetscAssertPointer(set, 2); 9297 PetscAssertPointer(flg, 3); 9298 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9299 *set = PETSC_TRUE; 9300 *flg = PetscBool3ToBool(A->spd); 9301 } else { 9302 *set = PETSC_FALSE; 9303 } 9304 PetscFunctionReturn(PETSC_SUCCESS); 9305 } 9306 9307 /*@ 9308 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9309 9310 Not Collective 9311 9312 Input Parameter: 9313 . A - the matrix to check 9314 9315 Output Parameters: 9316 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9317 - flg - the result (only valid if set is `PETSC_TRUE`) 9318 9319 Level: advanced 9320 9321 Notes: 9322 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9323 if you want it explicitly checked 9324 9325 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9326 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9327 9328 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9329 @*/ 9330 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9331 { 9332 PetscFunctionBegin; 9333 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9334 PetscAssertPointer(set, 2); 9335 PetscAssertPointer(flg, 3); 9336 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9337 *set = PETSC_TRUE; 9338 *flg = PetscBool3ToBool(A->hermitian); 9339 } else { 9340 *set = PETSC_FALSE; 9341 } 9342 PetscFunctionReturn(PETSC_SUCCESS); 9343 } 9344 9345 /*@ 9346 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9347 9348 Collective 9349 9350 Input Parameter: 9351 . A - the matrix to test 9352 9353 Output Parameter: 9354 . flg - the result 9355 9356 Level: intermediate 9357 9358 Notes: 9359 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9360 9361 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 9362 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9363 9364 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9365 @*/ 9366 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9367 { 9368 PetscFunctionBegin; 9369 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9370 PetscAssertPointer(flg, 2); 9371 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9372 *flg = PetscBool3ToBool(A->structurally_symmetric); 9373 } else { 9374 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9375 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9376 } 9377 PetscFunctionReturn(PETSC_SUCCESS); 9378 } 9379 9380 /*@ 9381 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9382 9383 Not Collective 9384 9385 Input Parameter: 9386 . A - the matrix to check 9387 9388 Output Parameters: 9389 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9390 - flg - the result (only valid if set is PETSC_TRUE) 9391 9392 Level: advanced 9393 9394 Notes: 9395 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 9396 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9397 9398 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9399 9400 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9401 @*/ 9402 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9403 { 9404 PetscFunctionBegin; 9405 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9406 PetscAssertPointer(set, 2); 9407 PetscAssertPointer(flg, 3); 9408 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9409 *set = PETSC_TRUE; 9410 *flg = PetscBool3ToBool(A->structurally_symmetric); 9411 } else { 9412 *set = PETSC_FALSE; 9413 } 9414 PetscFunctionReturn(PETSC_SUCCESS); 9415 } 9416 9417 /*@ 9418 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9419 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9420 9421 Not Collective 9422 9423 Input Parameter: 9424 . mat - the matrix 9425 9426 Output Parameters: 9427 + nstash - the size of the stash 9428 . reallocs - the number of additional mallocs incurred. 9429 . bnstash - the size of the block stash 9430 - breallocs - the number of additional mallocs incurred.in the block stash 9431 9432 Level: advanced 9433 9434 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9435 @*/ 9436 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9437 { 9438 PetscFunctionBegin; 9439 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9440 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9441 PetscFunctionReturn(PETSC_SUCCESS); 9442 } 9443 9444 /*@C 9445 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9446 parallel layout, `PetscLayout` for rows and columns 9447 9448 Collective 9449 9450 Input Parameter: 9451 . mat - the matrix 9452 9453 Output Parameters: 9454 + right - (optional) vector that the matrix can be multiplied against 9455 - left - (optional) vector that the matrix vector product can be stored in 9456 9457 Level: advanced 9458 9459 Notes: 9460 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()`. 9461 9462 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9463 9464 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9465 @*/ 9466 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9467 { 9468 PetscFunctionBegin; 9469 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9470 PetscValidType(mat, 1); 9471 if (mat->ops->getvecs) { 9472 PetscUseTypeMethod(mat, getvecs, right, left); 9473 } else { 9474 if (right) { 9475 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9476 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9477 PetscCall(VecSetType(*right, mat->defaultvectype)); 9478 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9479 if (mat->boundtocpu && mat->bindingpropagates) { 9480 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9481 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9482 } 9483 #endif 9484 } 9485 if (left) { 9486 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9487 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9488 PetscCall(VecSetType(*left, mat->defaultvectype)); 9489 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9490 if (mat->boundtocpu && mat->bindingpropagates) { 9491 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9492 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9493 } 9494 #endif 9495 } 9496 } 9497 PetscFunctionReturn(PETSC_SUCCESS); 9498 } 9499 9500 /*@C 9501 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9502 with default values. 9503 9504 Not Collective 9505 9506 Input Parameter: 9507 . info - the `MatFactorInfo` data structure 9508 9509 Level: developer 9510 9511 Notes: 9512 The solvers are generally used through the `KSP` and `PC` objects, for example 9513 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9514 9515 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9516 9517 Developer Note: 9518 The Fortran interface is not autogenerated as the 9519 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9520 9521 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9522 @*/ 9523 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9524 { 9525 PetscFunctionBegin; 9526 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9527 PetscFunctionReturn(PETSC_SUCCESS); 9528 } 9529 9530 /*@ 9531 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9532 9533 Collective 9534 9535 Input Parameters: 9536 + mat - the factored matrix 9537 - is - the index set defining the Schur indices (0-based) 9538 9539 Level: advanced 9540 9541 Notes: 9542 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9543 9544 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9545 9546 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9547 9548 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9549 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9550 @*/ 9551 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9552 { 9553 PetscErrorCode (*f)(Mat, IS); 9554 9555 PetscFunctionBegin; 9556 PetscValidType(mat, 1); 9557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9558 PetscValidType(is, 2); 9559 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9560 PetscCheckSameComm(mat, 1, is, 2); 9561 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9562 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9563 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9564 PetscCall(MatDestroy(&mat->schur)); 9565 PetscCall((*f)(mat, is)); 9566 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9567 PetscFunctionReturn(PETSC_SUCCESS); 9568 } 9569 9570 /*@ 9571 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9572 9573 Logically Collective 9574 9575 Input Parameters: 9576 + F - the factored matrix obtained by calling `MatGetFactor()` 9577 . S - location where to return the Schur complement, can be `NULL` 9578 - status - the status of the Schur complement matrix, can be `NULL` 9579 9580 Level: advanced 9581 9582 Notes: 9583 You must call `MatFactorSetSchurIS()` before calling this routine. 9584 9585 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9586 9587 The routine provides a copy of the Schur matrix stored within the solver data structures. 9588 The caller must destroy the object when it is no longer needed. 9589 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9590 9591 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) 9592 9593 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9594 9595 Developer Note: 9596 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9597 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9598 9599 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9600 @*/ 9601 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9602 { 9603 PetscFunctionBegin; 9604 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9605 if (S) PetscAssertPointer(S, 2); 9606 if (status) PetscAssertPointer(status, 3); 9607 if (S) { 9608 PetscErrorCode (*f)(Mat, Mat *); 9609 9610 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9611 if (f) { 9612 PetscCall((*f)(F, S)); 9613 } else { 9614 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9615 } 9616 } 9617 if (status) *status = F->schur_status; 9618 PetscFunctionReturn(PETSC_SUCCESS); 9619 } 9620 9621 /*@ 9622 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9623 9624 Logically Collective 9625 9626 Input Parameters: 9627 + F - the factored matrix obtained by calling `MatGetFactor()` 9628 . S - location where to return the Schur complement, can be `NULL` 9629 - status - the status of the Schur complement matrix, can be `NULL` 9630 9631 Level: advanced 9632 9633 Notes: 9634 You must call `MatFactorSetSchurIS()` before calling this routine. 9635 9636 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9637 9638 The routine returns a the Schur Complement stored within the data structures of the solver. 9639 9640 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9641 9642 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9643 9644 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9645 9646 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9647 9648 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9649 @*/ 9650 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9651 { 9652 PetscFunctionBegin; 9653 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9654 if (S) { 9655 PetscAssertPointer(S, 2); 9656 *S = F->schur; 9657 } 9658 if (status) { 9659 PetscAssertPointer(status, 3); 9660 *status = F->schur_status; 9661 } 9662 PetscFunctionReturn(PETSC_SUCCESS); 9663 } 9664 9665 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9666 { 9667 Mat S = F->schur; 9668 9669 PetscFunctionBegin; 9670 switch (F->schur_status) { 9671 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9672 case MAT_FACTOR_SCHUR_INVERTED: 9673 if (S) { 9674 S->ops->solve = NULL; 9675 S->ops->matsolve = NULL; 9676 S->ops->solvetranspose = NULL; 9677 S->ops->matsolvetranspose = NULL; 9678 S->ops->solveadd = NULL; 9679 S->ops->solvetransposeadd = NULL; 9680 S->factortype = MAT_FACTOR_NONE; 9681 PetscCall(PetscFree(S->solvertype)); 9682 } 9683 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9684 break; 9685 default: 9686 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9687 } 9688 PetscFunctionReturn(PETSC_SUCCESS); 9689 } 9690 9691 /*@ 9692 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9693 9694 Logically Collective 9695 9696 Input Parameters: 9697 + F - the factored matrix obtained by calling `MatGetFactor()` 9698 . S - location where the Schur complement is stored 9699 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9700 9701 Level: advanced 9702 9703 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9704 @*/ 9705 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9706 { 9707 PetscFunctionBegin; 9708 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9709 if (S) { 9710 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9711 *S = NULL; 9712 } 9713 F->schur_status = status; 9714 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9715 PetscFunctionReturn(PETSC_SUCCESS); 9716 } 9717 9718 /*@ 9719 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9720 9721 Logically Collective 9722 9723 Input Parameters: 9724 + F - the factored matrix obtained by calling `MatGetFactor()` 9725 . rhs - location where the right hand side of the Schur complement system is stored 9726 - sol - location where the solution of the Schur complement system has to be returned 9727 9728 Level: advanced 9729 9730 Notes: 9731 The sizes of the vectors should match the size of the Schur complement 9732 9733 Must be called after `MatFactorSetSchurIS()` 9734 9735 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9736 @*/ 9737 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9738 { 9739 PetscFunctionBegin; 9740 PetscValidType(F, 1); 9741 PetscValidType(rhs, 2); 9742 PetscValidType(sol, 3); 9743 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9744 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9745 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9746 PetscCheckSameComm(F, 1, rhs, 2); 9747 PetscCheckSameComm(F, 1, sol, 3); 9748 PetscCall(MatFactorFactorizeSchurComplement(F)); 9749 switch (F->schur_status) { 9750 case MAT_FACTOR_SCHUR_FACTORED: 9751 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9752 break; 9753 case MAT_FACTOR_SCHUR_INVERTED: 9754 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9755 break; 9756 default: 9757 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9758 } 9759 PetscFunctionReturn(PETSC_SUCCESS); 9760 } 9761 9762 /*@ 9763 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9764 9765 Logically Collective 9766 9767 Input Parameters: 9768 + F - the factored matrix obtained by calling `MatGetFactor()` 9769 . rhs - location where the right hand side of the Schur complement system is stored 9770 - sol - location where the solution of the Schur complement system has to be returned 9771 9772 Level: advanced 9773 9774 Notes: 9775 The sizes of the vectors should match the size of the Schur complement 9776 9777 Must be called after `MatFactorSetSchurIS()` 9778 9779 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9780 @*/ 9781 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9782 { 9783 PetscFunctionBegin; 9784 PetscValidType(F, 1); 9785 PetscValidType(rhs, 2); 9786 PetscValidType(sol, 3); 9787 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9788 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9789 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9790 PetscCheckSameComm(F, 1, rhs, 2); 9791 PetscCheckSameComm(F, 1, sol, 3); 9792 PetscCall(MatFactorFactorizeSchurComplement(F)); 9793 switch (F->schur_status) { 9794 case MAT_FACTOR_SCHUR_FACTORED: 9795 PetscCall(MatSolve(F->schur, rhs, sol)); 9796 break; 9797 case MAT_FACTOR_SCHUR_INVERTED: 9798 PetscCall(MatMult(F->schur, rhs, sol)); 9799 break; 9800 default: 9801 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9802 } 9803 PetscFunctionReturn(PETSC_SUCCESS); 9804 } 9805 9806 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9807 #if PetscDefined(HAVE_CUDA) 9808 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9809 #endif 9810 9811 /* Schur status updated in the interface */ 9812 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9813 { 9814 Mat S = F->schur; 9815 9816 PetscFunctionBegin; 9817 if (S) { 9818 PetscMPIInt size; 9819 PetscBool isdense, isdensecuda; 9820 9821 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9822 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9823 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9824 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9825 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9826 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9827 if (isdense) { 9828 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9829 } else if (isdensecuda) { 9830 #if defined(PETSC_HAVE_CUDA) 9831 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9832 #endif 9833 } 9834 // HIP?????????????? 9835 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9836 } 9837 PetscFunctionReturn(PETSC_SUCCESS); 9838 } 9839 9840 /*@ 9841 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9842 9843 Logically Collective 9844 9845 Input Parameter: 9846 . F - the factored matrix obtained by calling `MatGetFactor()` 9847 9848 Level: advanced 9849 9850 Notes: 9851 Must be called after `MatFactorSetSchurIS()`. 9852 9853 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9854 9855 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9856 @*/ 9857 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9858 { 9859 PetscFunctionBegin; 9860 PetscValidType(F, 1); 9861 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9862 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9863 PetscCall(MatFactorFactorizeSchurComplement(F)); 9864 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9865 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9866 PetscFunctionReturn(PETSC_SUCCESS); 9867 } 9868 9869 /*@ 9870 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9871 9872 Logically Collective 9873 9874 Input Parameter: 9875 . F - the factored matrix obtained by calling `MatGetFactor()` 9876 9877 Level: advanced 9878 9879 Note: 9880 Must be called after `MatFactorSetSchurIS()` 9881 9882 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9883 @*/ 9884 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9885 { 9886 MatFactorInfo info; 9887 9888 PetscFunctionBegin; 9889 PetscValidType(F, 1); 9890 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9891 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9892 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9893 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9894 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9895 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9896 } else { 9897 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9898 } 9899 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9900 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9901 PetscFunctionReturn(PETSC_SUCCESS); 9902 } 9903 9904 /*@ 9905 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9906 9907 Neighbor-wise Collective 9908 9909 Input Parameters: 9910 + A - the matrix 9911 . P - the projection matrix 9912 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9913 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9914 if the result is a dense matrix this is irrelevant 9915 9916 Output Parameter: 9917 . C - the product matrix 9918 9919 Level: intermediate 9920 9921 Notes: 9922 C will be created and must be destroyed by the user with `MatDestroy()`. 9923 9924 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9925 9926 Developer Note: 9927 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9928 9929 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9930 @*/ 9931 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9932 { 9933 PetscFunctionBegin; 9934 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9935 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9936 9937 if (scall == MAT_INITIAL_MATRIX) { 9938 PetscCall(MatProductCreate(A, P, NULL, C)); 9939 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9940 PetscCall(MatProductSetAlgorithm(*C, "default")); 9941 PetscCall(MatProductSetFill(*C, fill)); 9942 9943 (*C)->product->api_user = PETSC_TRUE; 9944 PetscCall(MatProductSetFromOptions(*C)); 9945 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); 9946 PetscCall(MatProductSymbolic(*C)); 9947 } else { /* scall == MAT_REUSE_MATRIX */ 9948 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9949 } 9950 9951 PetscCall(MatProductNumeric(*C)); 9952 (*C)->symmetric = A->symmetric; 9953 (*C)->spd = A->spd; 9954 PetscFunctionReturn(PETSC_SUCCESS); 9955 } 9956 9957 /*@ 9958 MatRARt - Creates the matrix product $C = R * A * R^T$ 9959 9960 Neighbor-wise Collective 9961 9962 Input Parameters: 9963 + A - the matrix 9964 . R - the projection matrix 9965 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9966 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9967 if the result is a dense matrix this is irrelevant 9968 9969 Output Parameter: 9970 . C - the product matrix 9971 9972 Level: intermediate 9973 9974 Notes: 9975 C will be created and must be destroyed by the user with `MatDestroy()`. 9976 9977 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9978 9979 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9980 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9981 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9982 We recommend using MatPtAP(). 9983 9984 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9985 @*/ 9986 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9987 { 9988 PetscFunctionBegin; 9989 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9990 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9991 9992 if (scall == MAT_INITIAL_MATRIX) { 9993 PetscCall(MatProductCreate(A, R, NULL, C)); 9994 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9995 PetscCall(MatProductSetAlgorithm(*C, "default")); 9996 PetscCall(MatProductSetFill(*C, fill)); 9997 9998 (*C)->product->api_user = PETSC_TRUE; 9999 PetscCall(MatProductSetFromOptions(*C)); 10000 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); 10001 PetscCall(MatProductSymbolic(*C)); 10002 } else { /* scall == MAT_REUSE_MATRIX */ 10003 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10004 } 10005 10006 PetscCall(MatProductNumeric(*C)); 10007 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10008 PetscFunctionReturn(PETSC_SUCCESS); 10009 } 10010 10011 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10012 { 10013 PetscFunctionBegin; 10014 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10015 10016 if (scall == MAT_INITIAL_MATRIX) { 10017 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10018 PetscCall(MatProductCreate(A, B, NULL, C)); 10019 PetscCall(MatProductSetType(*C, ptype)); 10020 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10021 PetscCall(MatProductSetFill(*C, fill)); 10022 10023 (*C)->product->api_user = PETSC_TRUE; 10024 PetscCall(MatProductSetFromOptions(*C)); 10025 PetscCall(MatProductSymbolic(*C)); 10026 } else { /* scall == MAT_REUSE_MATRIX */ 10027 Mat_Product *product = (*C)->product; 10028 PetscBool isdense; 10029 10030 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10031 if (isdense && product && product->type != ptype) { 10032 PetscCall(MatProductClear(*C)); 10033 product = NULL; 10034 } 10035 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10036 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10037 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10038 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10039 product = (*C)->product; 10040 product->fill = fill; 10041 product->api_user = PETSC_TRUE; 10042 product->clear = PETSC_TRUE; 10043 10044 PetscCall(MatProductSetType(*C, ptype)); 10045 PetscCall(MatProductSetFromOptions(*C)); 10046 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name); 10047 PetscCall(MatProductSymbolic(*C)); 10048 } else { /* user may change input matrices A or B when REUSE */ 10049 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10050 } 10051 } 10052 PetscCall(MatProductNumeric(*C)); 10053 PetscFunctionReturn(PETSC_SUCCESS); 10054 } 10055 10056 /*@ 10057 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10058 10059 Neighbor-wise Collective 10060 10061 Input Parameters: 10062 + A - the left matrix 10063 . B - the right matrix 10064 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10065 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10066 if the result is a dense matrix this is irrelevant 10067 10068 Output Parameter: 10069 . C - the product matrix 10070 10071 Notes: 10072 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10073 10074 `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 10075 call to this function with `MAT_INITIAL_MATRIX`. 10076 10077 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10078 10079 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`, 10080 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10081 10082 Example of Usage: 10083 .vb 10084 MatProductCreate(A,B,NULL,&C); 10085 MatProductSetType(C,MATPRODUCT_AB); 10086 MatProductSymbolic(C); 10087 MatProductNumeric(C); // compute C=A * B 10088 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10089 MatProductNumeric(C); 10090 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10091 MatProductNumeric(C); 10092 .ve 10093 10094 Level: intermediate 10095 10096 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10097 @*/ 10098 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10099 { 10100 PetscFunctionBegin; 10101 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10102 PetscFunctionReturn(PETSC_SUCCESS); 10103 } 10104 10105 /*@ 10106 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10107 10108 Neighbor-wise Collective 10109 10110 Input Parameters: 10111 + A - the left matrix 10112 . B - the right matrix 10113 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10114 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10115 10116 Output Parameter: 10117 . C - the product matrix 10118 10119 Options Database Key: 10120 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10121 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10122 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10123 10124 Level: intermediate 10125 10126 Notes: 10127 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10128 10129 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10130 10131 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10132 actually needed. 10133 10134 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10135 and for pairs of `MATMPIDENSE` matrices. 10136 10137 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10138 10139 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10140 @*/ 10141 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10142 { 10143 PetscFunctionBegin; 10144 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10145 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10146 PetscFunctionReturn(PETSC_SUCCESS); 10147 } 10148 10149 /*@ 10150 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10151 10152 Neighbor-wise Collective 10153 10154 Input Parameters: 10155 + A - the left matrix 10156 . B - the right matrix 10157 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10158 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10159 10160 Output Parameter: 10161 . C - the product matrix 10162 10163 Level: intermediate 10164 10165 Notes: 10166 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10167 10168 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10169 10170 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10171 10172 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10173 actually needed. 10174 10175 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10176 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10177 10178 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10179 @*/ 10180 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10181 { 10182 PetscFunctionBegin; 10183 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10184 PetscFunctionReturn(PETSC_SUCCESS); 10185 } 10186 10187 /*@ 10188 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10189 10190 Neighbor-wise Collective 10191 10192 Input Parameters: 10193 + A - the left matrix 10194 . B - the middle matrix 10195 . C - the right matrix 10196 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10197 - 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 10198 if the result is a dense matrix this is irrelevant 10199 10200 Output Parameter: 10201 . D - the product matrix 10202 10203 Level: intermediate 10204 10205 Notes: 10206 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10207 10208 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10209 10210 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10211 10212 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10213 actually needed. 10214 10215 If you have many matrices with the same non-zero structure to multiply, you 10216 should use `MAT_REUSE_MATRIX` in all calls but the first 10217 10218 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10219 @*/ 10220 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10221 { 10222 PetscFunctionBegin; 10223 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10224 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10225 10226 if (scall == MAT_INITIAL_MATRIX) { 10227 PetscCall(MatProductCreate(A, B, C, D)); 10228 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10229 PetscCall(MatProductSetAlgorithm(*D, "default")); 10230 PetscCall(MatProductSetFill(*D, fill)); 10231 10232 (*D)->product->api_user = PETSC_TRUE; 10233 PetscCall(MatProductSetFromOptions(*D)); 10234 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, 10235 ((PetscObject)C)->type_name); 10236 PetscCall(MatProductSymbolic(*D)); 10237 } else { /* user may change input matrices when REUSE */ 10238 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10239 } 10240 PetscCall(MatProductNumeric(*D)); 10241 PetscFunctionReturn(PETSC_SUCCESS); 10242 } 10243 10244 /*@ 10245 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10246 10247 Collective 10248 10249 Input Parameters: 10250 + mat - the matrix 10251 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10252 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10253 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10254 10255 Output Parameter: 10256 . matredundant - redundant matrix 10257 10258 Level: advanced 10259 10260 Notes: 10261 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10262 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10263 10264 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10265 calling it. 10266 10267 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10268 10269 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10270 @*/ 10271 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10272 { 10273 MPI_Comm comm; 10274 PetscMPIInt size; 10275 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10276 Mat_Redundant *redund = NULL; 10277 PetscSubcomm psubcomm = NULL; 10278 MPI_Comm subcomm_in = subcomm; 10279 Mat *matseq; 10280 IS isrow, iscol; 10281 PetscBool newsubcomm = PETSC_FALSE; 10282 10283 PetscFunctionBegin; 10284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10285 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10286 PetscAssertPointer(*matredundant, 5); 10287 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10288 } 10289 10290 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10291 if (size == 1 || nsubcomm == 1) { 10292 if (reuse == MAT_INITIAL_MATRIX) { 10293 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10294 } else { 10295 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"); 10296 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10297 } 10298 PetscFunctionReturn(PETSC_SUCCESS); 10299 } 10300 10301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10303 MatCheckPreallocated(mat, 1); 10304 10305 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10306 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10307 /* create psubcomm, then get subcomm */ 10308 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10309 PetscCallMPI(MPI_Comm_size(comm, &size)); 10310 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10311 10312 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10313 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10314 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10315 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10316 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10317 newsubcomm = PETSC_TRUE; 10318 PetscCall(PetscSubcommDestroy(&psubcomm)); 10319 } 10320 10321 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10322 if (reuse == MAT_INITIAL_MATRIX) { 10323 mloc_sub = PETSC_DECIDE; 10324 nloc_sub = PETSC_DECIDE; 10325 if (bs < 1) { 10326 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10327 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10328 } else { 10329 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10330 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10331 } 10332 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10333 rstart = rend - mloc_sub; 10334 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10335 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10336 PetscCall(ISSetIdentity(iscol)); 10337 } else { /* reuse == MAT_REUSE_MATRIX */ 10338 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"); 10339 /* retrieve subcomm */ 10340 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10341 redund = (*matredundant)->redundant; 10342 isrow = redund->isrow; 10343 iscol = redund->iscol; 10344 matseq = redund->matseq; 10345 } 10346 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10347 10348 /* get matredundant over subcomm */ 10349 if (reuse == MAT_INITIAL_MATRIX) { 10350 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10351 10352 /* create a supporting struct and attach it to C for reuse */ 10353 PetscCall(PetscNew(&redund)); 10354 (*matredundant)->redundant = redund; 10355 redund->isrow = isrow; 10356 redund->iscol = iscol; 10357 redund->matseq = matseq; 10358 if (newsubcomm) { 10359 redund->subcomm = subcomm; 10360 } else { 10361 redund->subcomm = MPI_COMM_NULL; 10362 } 10363 } else { 10364 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10365 } 10366 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10367 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10368 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10369 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10370 } 10371 #endif 10372 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10373 PetscFunctionReturn(PETSC_SUCCESS); 10374 } 10375 10376 /*@C 10377 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10378 a given `Mat`. Each submatrix can span multiple procs. 10379 10380 Collective 10381 10382 Input Parameters: 10383 + mat - the matrix 10384 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10385 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10386 10387 Output Parameter: 10388 . subMat - parallel sub-matrices each spanning a given `subcomm` 10389 10390 Level: advanced 10391 10392 Notes: 10393 The submatrix partition across processors is dictated by `subComm` a 10394 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10395 is not restricted to be grouped with consecutive original MPI processes. 10396 10397 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10398 map directly to the layout of the original matrix [wrt the local 10399 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10400 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10401 the `subMat`. However the offDiagMat looses some columns - and this is 10402 reconstructed with `MatSetValues()` 10403 10404 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10405 10406 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10407 @*/ 10408 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10409 { 10410 PetscMPIInt commsize, subCommSize; 10411 10412 PetscFunctionBegin; 10413 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10414 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10415 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10416 10417 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"); 10418 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10419 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10420 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10421 PetscFunctionReturn(PETSC_SUCCESS); 10422 } 10423 10424 /*@ 10425 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10426 10427 Not Collective 10428 10429 Input Parameters: 10430 + mat - matrix to extract local submatrix from 10431 . isrow - local row indices for submatrix 10432 - iscol - local column indices for submatrix 10433 10434 Output Parameter: 10435 . submat - the submatrix 10436 10437 Level: intermediate 10438 10439 Notes: 10440 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10441 10442 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10443 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10444 10445 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10446 `MatSetValuesBlockedLocal()` will also be implemented. 10447 10448 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10449 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10450 10451 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10452 @*/ 10453 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10454 { 10455 PetscFunctionBegin; 10456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10457 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10458 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10459 PetscCheckSameComm(isrow, 2, iscol, 3); 10460 PetscAssertPointer(submat, 4); 10461 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10462 10463 if (mat->ops->getlocalsubmatrix) { 10464 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10465 } else { 10466 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10467 } 10468 PetscFunctionReturn(PETSC_SUCCESS); 10469 } 10470 10471 /*@ 10472 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10473 10474 Not Collective 10475 10476 Input Parameters: 10477 + mat - matrix to extract local submatrix from 10478 . isrow - local row indices for submatrix 10479 . iscol - local column indices for submatrix 10480 - submat - the submatrix 10481 10482 Level: intermediate 10483 10484 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10485 @*/ 10486 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10487 { 10488 PetscFunctionBegin; 10489 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10490 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10491 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10492 PetscCheckSameComm(isrow, 2, iscol, 3); 10493 PetscAssertPointer(submat, 4); 10494 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10495 10496 if (mat->ops->restorelocalsubmatrix) { 10497 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10498 } else { 10499 PetscCall(MatDestroy(submat)); 10500 } 10501 *submat = NULL; 10502 PetscFunctionReturn(PETSC_SUCCESS); 10503 } 10504 10505 /*@ 10506 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10507 10508 Collective 10509 10510 Input Parameter: 10511 . mat - the matrix 10512 10513 Output Parameter: 10514 . is - if any rows have zero diagonals this contains the list of them 10515 10516 Level: developer 10517 10518 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10519 @*/ 10520 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10521 { 10522 PetscFunctionBegin; 10523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10524 PetscValidType(mat, 1); 10525 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10527 10528 if (!mat->ops->findzerodiagonals) { 10529 Vec diag; 10530 const PetscScalar *a; 10531 PetscInt *rows; 10532 PetscInt rStart, rEnd, r, nrow = 0; 10533 10534 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10535 PetscCall(MatGetDiagonal(mat, diag)); 10536 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10537 PetscCall(VecGetArrayRead(diag, &a)); 10538 for (r = 0; r < rEnd - rStart; ++r) 10539 if (a[r] == 0.0) ++nrow; 10540 PetscCall(PetscMalloc1(nrow, &rows)); 10541 nrow = 0; 10542 for (r = 0; r < rEnd - rStart; ++r) 10543 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10544 PetscCall(VecRestoreArrayRead(diag, &a)); 10545 PetscCall(VecDestroy(&diag)); 10546 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10547 } else { 10548 PetscUseTypeMethod(mat, findzerodiagonals, is); 10549 } 10550 PetscFunctionReturn(PETSC_SUCCESS); 10551 } 10552 10553 /*@ 10554 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10555 10556 Collective 10557 10558 Input Parameter: 10559 . mat - the matrix 10560 10561 Output Parameter: 10562 . is - contains the list of rows with off block diagonal entries 10563 10564 Level: developer 10565 10566 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10567 @*/ 10568 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10569 { 10570 PetscFunctionBegin; 10571 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10572 PetscValidType(mat, 1); 10573 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10574 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10575 10576 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10577 PetscFunctionReturn(PETSC_SUCCESS); 10578 } 10579 10580 /*@C 10581 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10582 10583 Collective; No Fortran Support 10584 10585 Input Parameter: 10586 . mat - the matrix 10587 10588 Output Parameter: 10589 . values - the block inverses in column major order (FORTRAN-like) 10590 10591 Level: advanced 10592 10593 Notes: 10594 The size of the blocks is determined by the block size of the matrix. 10595 10596 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10597 10598 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10599 10600 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10601 @*/ 10602 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10603 { 10604 PetscFunctionBegin; 10605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10606 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10607 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10608 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10609 PetscFunctionReturn(PETSC_SUCCESS); 10610 } 10611 10612 /*@C 10613 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10614 10615 Collective; No Fortran Support 10616 10617 Input Parameters: 10618 + mat - the matrix 10619 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10620 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10621 10622 Output Parameter: 10623 . values - the block inverses in column major order (FORTRAN-like) 10624 10625 Level: advanced 10626 10627 Notes: 10628 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10629 10630 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10631 10632 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10633 @*/ 10634 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10635 { 10636 PetscFunctionBegin; 10637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10638 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10639 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10640 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10641 PetscFunctionReturn(PETSC_SUCCESS); 10642 } 10643 10644 /*@ 10645 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10646 10647 Collective 10648 10649 Input Parameters: 10650 + A - the matrix 10651 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10652 10653 Level: advanced 10654 10655 Note: 10656 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10657 10658 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10659 @*/ 10660 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10661 { 10662 const PetscScalar *vals; 10663 PetscInt *dnnz; 10664 PetscInt m, rstart, rend, bs, i, j; 10665 10666 PetscFunctionBegin; 10667 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10668 PetscCall(MatGetBlockSize(A, &bs)); 10669 PetscCall(MatGetLocalSize(A, &m, NULL)); 10670 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10671 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10672 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10673 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10674 PetscCall(PetscFree(dnnz)); 10675 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10676 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10677 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10678 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10679 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10680 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10681 PetscFunctionReturn(PETSC_SUCCESS); 10682 } 10683 10684 /*@C 10685 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10686 via `MatTransposeColoringCreate()`. 10687 10688 Collective 10689 10690 Input Parameter: 10691 . c - coloring context 10692 10693 Level: intermediate 10694 10695 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10696 @*/ 10697 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10698 { 10699 MatTransposeColoring matcolor = *c; 10700 10701 PetscFunctionBegin; 10702 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10703 if (--((PetscObject)matcolor)->refct > 0) { 10704 matcolor = NULL; 10705 PetscFunctionReturn(PETSC_SUCCESS); 10706 } 10707 10708 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10709 PetscCall(PetscFree(matcolor->rows)); 10710 PetscCall(PetscFree(matcolor->den2sp)); 10711 PetscCall(PetscFree(matcolor->colorforcol)); 10712 PetscCall(PetscFree(matcolor->columns)); 10713 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10714 PetscCall(PetscHeaderDestroy(c)); 10715 PetscFunctionReturn(PETSC_SUCCESS); 10716 } 10717 10718 /*@C 10719 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10720 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10721 `MatTransposeColoring` to sparse `B`. 10722 10723 Collective 10724 10725 Input Parameters: 10726 + coloring - coloring context created with `MatTransposeColoringCreate()` 10727 - B - sparse matrix 10728 10729 Output Parameter: 10730 . Btdense - dense matrix $B^T$ 10731 10732 Level: developer 10733 10734 Note: 10735 These are used internally for some implementations of `MatRARt()` 10736 10737 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10738 @*/ 10739 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10740 { 10741 PetscFunctionBegin; 10742 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10743 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10744 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10745 10746 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10747 PetscFunctionReturn(PETSC_SUCCESS); 10748 } 10749 10750 /*@C 10751 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10752 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10753 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10754 $C_{sp}$ from $C_{den}$. 10755 10756 Collective 10757 10758 Input Parameters: 10759 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10760 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10761 10762 Output Parameter: 10763 . Csp - sparse matrix 10764 10765 Level: developer 10766 10767 Note: 10768 These are used internally for some implementations of `MatRARt()` 10769 10770 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10771 @*/ 10772 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10773 { 10774 PetscFunctionBegin; 10775 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10776 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10777 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10778 10779 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10780 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10781 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10782 PetscFunctionReturn(PETSC_SUCCESS); 10783 } 10784 10785 /*@C 10786 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10787 10788 Collective 10789 10790 Input Parameters: 10791 + mat - the matrix product C 10792 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10793 10794 Output Parameter: 10795 . color - the new coloring context 10796 10797 Level: intermediate 10798 10799 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10800 `MatTransColoringApplyDenToSp()` 10801 @*/ 10802 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10803 { 10804 MatTransposeColoring c; 10805 MPI_Comm comm; 10806 10807 PetscFunctionBegin; 10808 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10809 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10810 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10811 10812 c->ctype = iscoloring->ctype; 10813 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10814 10815 *color = c; 10816 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10817 PetscFunctionReturn(PETSC_SUCCESS); 10818 } 10819 10820 /*@ 10821 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10822 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10823 same, otherwise it will be larger 10824 10825 Not Collective 10826 10827 Input Parameter: 10828 . mat - the matrix 10829 10830 Output Parameter: 10831 . state - the current state 10832 10833 Level: intermediate 10834 10835 Notes: 10836 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10837 different matrices 10838 10839 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10840 10841 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10842 10843 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10844 @*/ 10845 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10846 { 10847 PetscFunctionBegin; 10848 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10849 *state = mat->nonzerostate; 10850 PetscFunctionReturn(PETSC_SUCCESS); 10851 } 10852 10853 /*@ 10854 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10855 matrices from each processor 10856 10857 Collective 10858 10859 Input Parameters: 10860 + comm - the communicators the parallel matrix will live on 10861 . seqmat - the input sequential matrices 10862 . n - number of local columns (or `PETSC_DECIDE`) 10863 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10864 10865 Output Parameter: 10866 . mpimat - the parallel matrix generated 10867 10868 Level: developer 10869 10870 Note: 10871 The number of columns of the matrix in EACH processor MUST be the same. 10872 10873 .seealso: [](ch_matrices), `Mat` 10874 @*/ 10875 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10876 { 10877 PetscMPIInt size; 10878 10879 PetscFunctionBegin; 10880 PetscCallMPI(MPI_Comm_size(comm, &size)); 10881 if (size == 1) { 10882 if (reuse == MAT_INITIAL_MATRIX) { 10883 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10884 } else { 10885 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10886 } 10887 PetscFunctionReturn(PETSC_SUCCESS); 10888 } 10889 10890 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"); 10891 10892 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10893 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10894 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10895 PetscFunctionReturn(PETSC_SUCCESS); 10896 } 10897 10898 /*@ 10899 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10900 10901 Collective 10902 10903 Input Parameters: 10904 + A - the matrix to create subdomains from 10905 - N - requested number of subdomains 10906 10907 Output Parameters: 10908 + n - number of subdomains resulting on this MPI process 10909 - iss - `IS` list with indices of subdomains on this MPI process 10910 10911 Level: advanced 10912 10913 Note: 10914 The number of subdomains must be smaller than the communicator size 10915 10916 .seealso: [](ch_matrices), `Mat`, `IS` 10917 @*/ 10918 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10919 { 10920 MPI_Comm comm, subcomm; 10921 PetscMPIInt size, rank, color; 10922 PetscInt rstart, rend, k; 10923 10924 PetscFunctionBegin; 10925 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10926 PetscCallMPI(MPI_Comm_size(comm, &size)); 10927 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10928 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); 10929 *n = 1; 10930 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10931 color = rank / k; 10932 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10933 PetscCall(PetscMalloc1(1, iss)); 10934 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10935 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10936 PetscCallMPI(MPI_Comm_free(&subcomm)); 10937 PetscFunctionReturn(PETSC_SUCCESS); 10938 } 10939 10940 /*@ 10941 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10942 10943 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10944 If they are not the same, uses `MatMatMatMult()`. 10945 10946 Once the coarse grid problem is constructed, correct for interpolation operators 10947 that are not of full rank, which can legitimately happen in the case of non-nested 10948 geometric multigrid. 10949 10950 Input Parameters: 10951 + restrct - restriction operator 10952 . dA - fine grid matrix 10953 . interpolate - interpolation operator 10954 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10955 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10956 10957 Output Parameter: 10958 . A - the Galerkin coarse matrix 10959 10960 Options Database Key: 10961 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10962 10963 Level: developer 10964 10965 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10966 @*/ 10967 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10968 { 10969 IS zerorows; 10970 Vec diag; 10971 10972 PetscFunctionBegin; 10973 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10974 /* Construct the coarse grid matrix */ 10975 if (interpolate == restrct) { 10976 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10977 } else { 10978 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10979 } 10980 10981 /* If the interpolation matrix is not of full rank, A will have zero rows. 10982 This can legitimately happen in the case of non-nested geometric multigrid. 10983 In that event, we set the rows of the matrix to the rows of the identity, 10984 ignoring the equations (as the RHS will also be zero). */ 10985 10986 PetscCall(MatFindZeroRows(*A, &zerorows)); 10987 10988 if (zerorows != NULL) { /* if there are any zero rows */ 10989 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10990 PetscCall(MatGetDiagonal(*A, diag)); 10991 PetscCall(VecISSet(diag, zerorows, 1.0)); 10992 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10993 PetscCall(VecDestroy(&diag)); 10994 PetscCall(ISDestroy(&zerorows)); 10995 } 10996 PetscFunctionReturn(PETSC_SUCCESS); 10997 } 10998 10999 /*@C 11000 MatSetOperation - Allows user to set a matrix operation for any matrix type 11001 11002 Logically Collective 11003 11004 Input Parameters: 11005 + mat - the matrix 11006 . op - the name of the operation 11007 - f - the function that provides the operation 11008 11009 Level: developer 11010 11011 Example Usage: 11012 .vb 11013 extern PetscErrorCode usermult(Mat, Vec, Vec); 11014 11015 PetscCall(MatCreateXXX(comm, ..., &A)); 11016 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 11017 .ve 11018 11019 Notes: 11020 See the file `include/petscmat.h` for a complete list of matrix 11021 operations, which all have the form MATOP_<OPERATION>, where 11022 <OPERATION> is the name (in all capital letters) of the 11023 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11024 11025 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11026 sequence as the usual matrix interface routines, since they 11027 are intended to be accessed via the usual matrix interface 11028 routines, e.g., 11029 .vb 11030 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11031 .ve 11032 11033 In particular each function MUST return `PETSC_SUCCESS` on success and 11034 nonzero on failure. 11035 11036 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11037 11038 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11039 @*/ 11040 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11041 { 11042 PetscFunctionBegin; 11043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11044 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11045 (((void (**)(void))mat->ops)[op]) = f; 11046 PetscFunctionReturn(PETSC_SUCCESS); 11047 } 11048 11049 /*@C 11050 MatGetOperation - Gets a matrix operation for any matrix type. 11051 11052 Not Collective 11053 11054 Input Parameters: 11055 + mat - the matrix 11056 - op - the name of the operation 11057 11058 Output Parameter: 11059 . f - the function that provides the operation 11060 11061 Level: developer 11062 11063 Example Usage: 11064 .vb 11065 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11066 11067 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11068 .ve 11069 11070 Notes: 11071 See the file include/petscmat.h for a complete list of matrix 11072 operations, which all have the form MATOP_<OPERATION>, where 11073 <OPERATION> is the name (in all capital letters) of the 11074 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11075 11076 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11077 11078 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11079 @*/ 11080 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11081 { 11082 PetscFunctionBegin; 11083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11084 *f = (((void (**)(void))mat->ops)[op]); 11085 PetscFunctionReturn(PETSC_SUCCESS); 11086 } 11087 11088 /*@ 11089 MatHasOperation - Determines whether the given matrix supports the particular operation. 11090 11091 Not Collective 11092 11093 Input Parameters: 11094 + mat - the matrix 11095 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11096 11097 Output Parameter: 11098 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11099 11100 Level: advanced 11101 11102 Note: 11103 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11104 11105 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11106 @*/ 11107 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11108 { 11109 PetscFunctionBegin; 11110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11111 PetscAssertPointer(has, 3); 11112 if (mat->ops->hasoperation) { 11113 PetscUseTypeMethod(mat, hasoperation, op, has); 11114 } else { 11115 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11116 else { 11117 *has = PETSC_FALSE; 11118 if (op == MATOP_CREATE_SUBMATRIX) { 11119 PetscMPIInt size; 11120 11121 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11122 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11123 } 11124 } 11125 } 11126 PetscFunctionReturn(PETSC_SUCCESS); 11127 } 11128 11129 /*@ 11130 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11131 11132 Collective 11133 11134 Input Parameter: 11135 . mat - the matrix 11136 11137 Output Parameter: 11138 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11139 11140 Level: beginner 11141 11142 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11143 @*/ 11144 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11145 { 11146 PetscFunctionBegin; 11147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11148 PetscValidType(mat, 1); 11149 PetscAssertPointer(cong, 2); 11150 if (!mat->rmap || !mat->cmap) { 11151 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11152 PetscFunctionReturn(PETSC_SUCCESS); 11153 } 11154 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11155 PetscCall(PetscLayoutSetUp(mat->rmap)); 11156 PetscCall(PetscLayoutSetUp(mat->cmap)); 11157 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11158 if (*cong) mat->congruentlayouts = 1; 11159 else mat->congruentlayouts = 0; 11160 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11161 PetscFunctionReturn(PETSC_SUCCESS); 11162 } 11163 11164 PetscErrorCode MatSetInf(Mat A) 11165 { 11166 PetscFunctionBegin; 11167 PetscUseTypeMethod(A, setinf); 11168 PetscFunctionReturn(PETSC_SUCCESS); 11169 } 11170 11171 /*@C 11172 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 11173 and possibly removes small values from the graph structure. 11174 11175 Collective 11176 11177 Input Parameters: 11178 + A - the matrix 11179 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11180 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11181 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11182 11183 Output Parameter: 11184 . graph - the resulting graph 11185 11186 Level: advanced 11187 11188 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11189 @*/ 11190 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11191 { 11192 PetscFunctionBegin; 11193 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11194 PetscValidType(A, 1); 11195 PetscValidLogicalCollectiveBool(A, scale, 3); 11196 PetscAssertPointer(graph, 5); 11197 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11198 PetscFunctionReturn(PETSC_SUCCESS); 11199 } 11200 11201 /*@ 11202 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11203 meaning the same memory is used for the matrix, and no new memory is allocated. 11204 11205 Collective 11206 11207 Input Parameters: 11208 + A - the matrix 11209 - 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 11210 11211 Level: intermediate 11212 11213 Developer Note: 11214 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11215 of the arrays in the data structure are unneeded. 11216 11217 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11218 @*/ 11219 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11220 { 11221 PetscFunctionBegin; 11222 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11223 PetscUseTypeMethod(A, eliminatezeros, keep); 11224 PetscFunctionReturn(PETSC_SUCCESS); 11225 } 11226