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