1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n, st; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 207 PetscCall(MatGetSize(mat, &N, NULL)); 208 PetscCall(MatGetLocalSize(mat, &n, NULL)); 209 PetscCall(VecSet(l, 0.0)); 210 PetscCall(VecSetRandom(r, NULL)); 211 PetscCall(MatMult(mat, r, l)); 212 PetscCall(VecGetArrayRead(l, &al)); 213 } else { /* nonzero columns */ 214 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 215 PetscCall(MatGetSize(mat, NULL, &N)); 216 PetscCall(MatGetLocalSize(mat, NULL, &n)); 217 PetscCall(VecSet(r, 0.0)); 218 PetscCall(VecSetRandom(l, NULL)); 219 PetscCall(MatMultTranspose(mat, l, r)); 220 PetscCall(VecGetArrayRead(r, &al)); 221 } 222 if (tol <= 0.0) { 223 for (i = 0, nz = 0; i < n; i++) 224 if (al[i] != 0.0) nz++; 225 } else { 226 for (i = 0, nz = 0; i < n; i++) 227 if (PetscAbsScalar(al[i]) > tol) nz++; 228 } 229 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 230 if (gnz != N) { 231 PetscInt *nzr; 232 PetscCall(PetscMalloc1(nz, &nzr)); 233 if (nz) { 234 if (tol < 0) { 235 for (i = 0, nz = 0; i < n; i++) 236 if (al[i] != 0.0) nzr[nz++] = i + st; 237 } else { 238 for (i = 0, nz = 0; i < n; i++) 239 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 240 } 241 } 242 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 243 } else *nonzero = NULL; 244 if (!cols) { /* nonzero rows */ 245 PetscCall(VecRestoreArrayRead(l, &al)); 246 } else { 247 PetscCall(VecRestoreArrayRead(r, &al)); 248 } 249 PetscCall(VecDestroy(&l)); 250 PetscCall(VecDestroy(&r)); 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 /*@ 255 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 256 257 Input Parameter: 258 . mat - the matrix 259 260 Output Parameter: 261 . keptrows - the rows that are not completely zero 262 263 Level: intermediate 264 265 Note: 266 `keptrows` is set to `NULL` if all rows are nonzero. 267 268 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 269 @*/ 270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 271 { 272 PetscFunctionBegin; 273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 274 PetscValidType(mat, 1); 275 PetscAssertPointer(keptrows, 2); 276 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 277 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 278 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 279 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 280 PetscFunctionReturn(PETSC_SUCCESS); 281 } 282 283 /*@ 284 MatFindZeroRows - Locate all rows that are completely zero in the matrix 285 286 Input Parameter: 287 . mat - the matrix 288 289 Output Parameter: 290 . zerorows - the rows that are completely zero 291 292 Level: intermediate 293 294 Note: 295 `zerorows` is set to `NULL` if no rows are zero. 296 297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 298 @*/ 299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 300 { 301 IS keptrows; 302 PetscInt m, n; 303 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 306 PetscValidType(mat, 1); 307 PetscAssertPointer(zerorows, 2); 308 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 309 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 310 In keeping with this convention, we set zerorows to NULL if there are no zero 311 rows. */ 312 if (keptrows == NULL) { 313 *zerorows = NULL; 314 } else { 315 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 316 PetscCall(ISComplement(keptrows, m, n, zerorows)); 317 PetscCall(ISDestroy(&keptrows)); 318 } 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 324 325 Not Collective 326 327 Input Parameter: 328 . A - the matrix 329 330 Output Parameter: 331 . a - the diagonal part (which is a SEQUENTIAL matrix) 332 333 Level: advanced 334 335 Notes: 336 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 337 338 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 339 340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 341 @*/ 342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 343 { 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 346 PetscValidType(A, 1); 347 PetscAssertPointer(a, 2); 348 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 349 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 350 else { 351 PetscMPIInt size; 352 353 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 354 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 355 *a = A; 356 } 357 PetscFunctionReturn(PETSC_SUCCESS); 358 } 359 360 /*@ 361 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 362 363 Collective 364 365 Input Parameter: 366 . mat - the matrix 367 368 Output Parameter: 369 . trace - the sum of the diagonal entries 370 371 Level: advanced 372 373 .seealso: [](ch_matrices), `Mat` 374 @*/ 375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 376 { 377 Vec diag; 378 379 PetscFunctionBegin; 380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 381 PetscAssertPointer(trace, 2); 382 PetscCall(MatCreateVecs(mat, &diag, NULL)); 383 PetscCall(MatGetDiagonal(mat, diag)); 384 PetscCall(VecSum(diag, trace)); 385 PetscCall(VecDestroy(&diag)); 386 PetscFunctionReturn(PETSC_SUCCESS); 387 } 388 389 /*@ 390 MatRealPart - Zeros out the imaginary part of the matrix 391 392 Logically Collective 393 394 Input Parameter: 395 . mat - the matrix 396 397 Level: advanced 398 399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 400 @*/ 401 PetscErrorCode MatRealPart(Mat mat) 402 { 403 PetscFunctionBegin; 404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 405 PetscValidType(mat, 1); 406 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 407 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 408 MatCheckPreallocated(mat, 1); 409 PetscUseTypeMethod(mat, realpart); 410 PetscFunctionReturn(PETSC_SUCCESS); 411 } 412 413 /*@C 414 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 415 416 Collective 417 418 Input Parameter: 419 . mat - the matrix 420 421 Output Parameters: 422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 423 - ghosts - the global indices of the ghost points 424 425 Level: advanced 426 427 Note: 428 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 429 430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 431 @*/ 432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 433 { 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 436 PetscValidType(mat, 1); 437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 439 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 440 else { 441 if (nghosts) *nghosts = 0; 442 if (ghosts) *ghosts = NULL; 443 } 444 PetscFunctionReturn(PETSC_SUCCESS); 445 } 446 447 /*@ 448 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 449 450 Logically Collective 451 452 Input Parameter: 453 . mat - the matrix 454 455 Level: advanced 456 457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 458 @*/ 459 PetscErrorCode MatImaginaryPart(Mat mat) 460 { 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 463 PetscValidType(mat, 1); 464 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 465 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 466 MatCheckPreallocated(mat, 1); 467 PetscUseTypeMethod(mat, imaginarypart); 468 PetscFunctionReturn(PETSC_SUCCESS); 469 } 470 471 /*@ 472 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 473 474 Not Collective 475 476 Input Parameter: 477 . mat - the matrix 478 479 Output Parameters: 480 + missing - is any diagonal entry missing 481 - dd - first diagonal entry that is missing (optional) on this process 482 483 Level: advanced 484 485 Note: 486 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 487 488 .seealso: [](ch_matrices), `Mat` 489 @*/ 490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 491 { 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 494 PetscValidType(mat, 1); 495 PetscAssertPointer(missing, 2); 496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 498 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 503 /*@C 504 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 505 for each row that you get to ensure that your application does 506 not bleed memory. 507 508 Not Collective 509 510 Input Parameters: 511 + mat - the matrix 512 - row - the row to get 513 514 Output Parameters: 515 + ncols - if not `NULL`, the number of nonzeros in `row` 516 . cols - if not `NULL`, the column numbers 517 - vals - if not `NULL`, the numerical values 518 519 Level: advanced 520 521 Notes: 522 This routine is provided for people who need to have direct access 523 to the structure of a matrix. We hope that we provide enough 524 high-level matrix routines that few users will need it. 525 526 `MatGetRow()` always returns 0-based column indices, regardless of 527 whether the internal representation is 0-based (default) or 1-based. 528 529 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 530 not wish to extract these quantities. 531 532 The user can only examine the values extracted with `MatGetRow()`; 533 the values CANNOT be altered. To change the matrix entries, one 534 must use `MatSetValues()`. 535 536 You can only have one call to `MatGetRow()` outstanding for a particular 537 matrix at a time, per processor. `MatGetRow()` can only obtain rows 538 associated with the given processor, it cannot get rows from the 539 other processors; for that we suggest using `MatCreateSubMatrices()`, then 540 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 541 is in the global number of rows. 542 543 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 544 545 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 546 547 Fortran Note: 548 The calling sequence is 549 .vb 550 MatGetRow(matrix,row,ncols,cols,values,ierr) 551 Mat matrix (input) 552 integer row (input) 553 integer ncols (output) 554 integer cols(maxcols) (output) 555 double precision (or double complex) values(maxcols) output 556 .ve 557 where maxcols >= maximum nonzeros in any row of the matrix. 558 559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 560 @*/ 561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 562 { 563 PetscInt incols; 564 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 567 PetscValidType(mat, 1); 568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 570 MatCheckPreallocated(mat, 1); 571 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 572 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 573 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 574 if (ncols) *ncols = incols; 575 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 576 PetscFunctionReturn(PETSC_SUCCESS); 577 } 578 579 /*@ 580 MatConjugate - replaces the matrix values with their complex conjugates 581 582 Logically Collective 583 584 Input Parameter: 585 . mat - the matrix 586 587 Level: advanced 588 589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 590 @*/ 591 PetscErrorCode MatConjugate(Mat mat) 592 { 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 596 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 597 PetscUseTypeMethod(mat, conjugate); 598 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 599 } 600 PetscFunctionReturn(PETSC_SUCCESS); 601 } 602 603 /*@C 604 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 605 606 Not Collective 607 608 Input Parameters: 609 + mat - the matrix 610 . row - the row to get 611 . ncols - the number of nonzeros 612 . cols - the columns of the nonzeros 613 - vals - if nonzero the column values 614 615 Level: advanced 616 617 Notes: 618 This routine should be called after you have finished examining the entries. 619 620 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 621 us of the array after it has been restored. If you pass `NULL`, it will 622 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 623 624 Fortran Notes: 625 The calling sequence is 626 .vb 627 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 628 Mat matrix (input) 629 integer row (input) 630 integer ncols (output) 631 integer cols(maxcols) (output) 632 double precision (or double complex) values(maxcols) output 633 .ve 634 Where maxcols >= maximum nonzeros in any row of the matrix. 635 636 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 637 before another call to `MatGetRow()` can be made. 638 639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 640 @*/ 641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 642 { 643 PetscFunctionBegin; 644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 645 if (ncols) PetscAssertPointer(ncols, 3); 646 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 647 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 648 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 649 if (ncols) *ncols = 0; 650 if (cols) *cols = NULL; 651 if (vals) *vals = NULL; 652 PetscFunctionReturn(PETSC_SUCCESS); 653 } 654 655 /*@ 656 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 657 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 658 659 Not Collective 660 661 Input Parameter: 662 . mat - the matrix 663 664 Level: advanced 665 666 Note: 667 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 668 669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 670 @*/ 671 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 672 { 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 675 PetscValidType(mat, 1); 676 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 677 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 678 MatCheckPreallocated(mat, 1); 679 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 680 PetscUseTypeMethod(mat, getrowuppertriangular); 681 PetscFunctionReturn(PETSC_SUCCESS); 682 } 683 684 /*@ 685 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 686 687 Not Collective 688 689 Input Parameter: 690 . mat - the matrix 691 692 Level: advanced 693 694 Note: 695 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 696 697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 698 @*/ 699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 700 { 701 PetscFunctionBegin; 702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 703 PetscValidType(mat, 1); 704 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 705 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 706 MatCheckPreallocated(mat, 1); 707 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 708 PetscUseTypeMethod(mat, restorerowuppertriangular); 709 PetscFunctionReturn(PETSC_SUCCESS); 710 } 711 712 /*@C 713 MatSetOptionsPrefix - Sets the prefix used for searching for all 714 `Mat` options in the database. 715 716 Logically Collective 717 718 Input Parameters: 719 + A - the matrix 720 - prefix - the prefix to prepend to all option names 721 722 Level: advanced 723 724 Notes: 725 A hyphen (-) must NOT be given at the beginning of the prefix name. 726 The first character of all runtime options is AUTOMATICALLY the hyphen. 727 728 This is NOT used for options for the factorization of the matrix. Normally the 729 prefix is automatically passed in from the PC calling the factorization. To set 730 it directly use `MatSetOptionsPrefixFactor()` 731 732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 733 @*/ 734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 735 { 736 PetscFunctionBegin; 737 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 738 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 739 PetscFunctionReturn(PETSC_SUCCESS); 740 } 741 742 /*@C 743 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 744 for matrices created with `MatGetFactor()` 745 746 Logically Collective 747 748 Input Parameters: 749 + A - the matrix 750 - prefix - the prefix to prepend to all option names for the factored matrix 751 752 Level: developer 753 754 Notes: 755 A hyphen (-) must NOT be given at the beginning of the prefix name. 756 The first character of all runtime options is AUTOMATICALLY the hyphen. 757 758 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 759 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 760 761 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 762 @*/ 763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 764 { 765 PetscFunctionBegin; 766 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 767 if (prefix) { 768 PetscAssertPointer(prefix, 2); 769 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 770 if (prefix != A->factorprefix) { 771 PetscCall(PetscFree(A->factorprefix)); 772 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 773 } 774 } else PetscCall(PetscFree(A->factorprefix)); 775 PetscFunctionReturn(PETSC_SUCCESS); 776 } 777 778 /*@C 779 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 780 for matrices created with `MatGetFactor()` 781 782 Logically Collective 783 784 Input Parameters: 785 + A - the matrix 786 - prefix - the prefix to prepend to all option names for the factored matrix 787 788 Level: developer 789 790 Notes: 791 A hyphen (-) must NOT be given at the beginning of the prefix name. 792 The first character of all runtime options is AUTOMATICALLY the hyphen. 793 794 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 795 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 796 797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 798 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 799 `MatSetOptionsPrefix()` 800 @*/ 801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 802 { 803 size_t len1, len2, new_len; 804 805 PetscFunctionBegin; 806 PetscValidHeader(A, 1); 807 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 808 if (!A->factorprefix) { 809 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 810 PetscFunctionReturn(PETSC_SUCCESS); 811 } 812 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 813 814 PetscCall(PetscStrlen(A->factorprefix, &len1)); 815 PetscCall(PetscStrlen(prefix, &len2)); 816 new_len = len1 + len2 + 1; 817 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 818 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 819 PetscFunctionReturn(PETSC_SUCCESS); 820 } 821 822 /*@C 823 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 824 matrix options in the database. 825 826 Logically Collective 827 828 Input Parameters: 829 + A - the matrix 830 - prefix - the prefix to prepend to all option names 831 832 Level: advanced 833 834 Note: 835 A hyphen (-) must NOT be given at the beginning of the prefix name. 836 The first character of all runtime options is AUTOMATICALLY the hyphen. 837 838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 839 @*/ 840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 844 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 845 PetscFunctionReturn(PETSC_SUCCESS); 846 } 847 848 /*@C 849 MatGetOptionsPrefix - Gets the prefix used for searching for all 850 matrix options in the database. 851 852 Not Collective 853 854 Input Parameter: 855 . A - the matrix 856 857 Output Parameter: 858 . prefix - pointer to the prefix string used 859 860 Level: advanced 861 862 Fortran Note: 863 The user should pass in a string `prefix` of 864 sufficient length to hold the prefix. 865 866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 867 @*/ 868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 869 { 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 872 PetscAssertPointer(prefix, 2); 873 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 874 PetscFunctionReturn(PETSC_SUCCESS); 875 } 876 877 /*@ 878 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 879 880 Collective 881 882 Input Parameter: 883 . A - the matrix 884 885 Level: beginner 886 887 Notes: 888 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 889 890 Users can reset the preallocation to access the original memory. 891 892 Currently only supported for `MATAIJ` matrices. 893 894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 895 @*/ 896 PetscErrorCode MatResetPreallocation(Mat A) 897 { 898 PetscFunctionBegin; 899 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 900 PetscValidType(A, 1); 901 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 902 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 903 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 904 PetscFunctionReturn(PETSC_SUCCESS); 905 } 906 907 /*@ 908 MatSetUp - Sets up the internal matrix data structures for later use. 909 910 Collective 911 912 Input Parameter: 913 . A - the matrix 914 915 Level: intermediate 916 917 Notes: 918 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 919 setting values in the matrix. 920 921 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 922 923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 924 @*/ 925 PetscErrorCode MatSetUp(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 if (!((PetscObject)A)->type_name) { 930 PetscMPIInt size; 931 932 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 933 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 934 } 935 if (!A->preallocated) PetscTryTypeMethod(A, setup); 936 PetscCall(PetscLayoutSetUp(A->rmap)); 937 PetscCall(PetscLayoutSetUp(A->cmap)); 938 A->preallocated = PETSC_TRUE; 939 PetscFunctionReturn(PETSC_SUCCESS); 940 } 941 942 #if defined(PETSC_HAVE_SAWS) 943 #include <petscviewersaws.h> 944 #endif 945 946 /* 947 If threadsafety is on extraneous matrices may be printed 948 949 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 950 */ 951 #if !defined(PETSC_HAVE_THREADSAFETY) 952 static PetscInt insidematview = 0; 953 #endif 954 955 /*@C 956 MatViewFromOptions - View properties of the matrix based on options set in the options database 957 958 Collective 959 960 Input Parameters: 961 + A - the matrix 962 . obj - optional additional object that provides the options prefix to use 963 - name - command line option 964 965 Options Database Key: 966 . -mat_view [viewertype]:... - the viewer and its options 967 968 Level: intermediate 969 970 Note: 971 .vb 972 If no value is provided ascii:stdout is used 973 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 974 for example ascii::ascii_info prints just the information about the object not all details 975 unless :append is given filename opens in write mode, overwriting what was already there 976 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 977 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 978 socket[:port] defaults to the standard output port 979 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 980 .ve 981 982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 983 @*/ 984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 985 { 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 988 #if !defined(PETSC_HAVE_THREADSAFETY) 989 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 990 #endif 991 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 992 PetscFunctionReturn(PETSC_SUCCESS); 993 } 994 995 /*@C 996 MatView - display information about a matrix in a variety ways 997 998 Collective 999 1000 Input Parameters: 1001 + mat - the matrix 1002 - viewer - visualization context 1003 1004 Options Database Keys: 1005 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1006 . -mat_view ::ascii_info_detail - Prints more detailed info 1007 . -mat_view - Prints matrix in ASCII format 1008 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1009 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1010 . -display <name> - Sets display name (default is host) 1011 . -draw_pause <sec> - Sets number of seconds to pause after display 1012 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1013 . -viewer_socket_machine <machine> - - 1014 . -viewer_socket_port <port> - - 1015 . -mat_view binary - save matrix to file in binary format 1016 - -viewer_binary_filename <name> - - 1017 1018 Level: beginner 1019 1020 Notes: 1021 The available visualization contexts include 1022 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1023 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1024 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1025 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1026 1027 The user can open alternative visualization contexts with 1028 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1029 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1030 specified file; corresponding input uses `MatLoad()` 1031 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1032 an X window display 1033 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1034 Currently only the `MATSEQDENSE` and `MATAIJ` 1035 matrix types support the Socket viewer. 1036 1037 The user can call `PetscViewerPushFormat()` to specify the output 1038 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1039 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1040 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1041 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1042 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1043 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1044 format common among all matrix types 1045 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1046 format (which is in many cases the same as the default) 1047 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1048 size and structure (not the matrix entries) 1049 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1050 the matrix structure 1051 1052 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1053 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1054 1055 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1056 1057 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1058 viewer is used. 1059 1060 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1061 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1062 1063 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1064 and then use the following mouse functions. 1065 .vb 1066 left mouse: zoom in 1067 middle mouse: zoom out 1068 right mouse: continue with the simulation 1069 .ve 1070 1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1072 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1073 @*/ 1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1075 { 1076 PetscInt rows, cols, rbs, cbs; 1077 PetscBool isascii, isstring, issaws; 1078 PetscViewerFormat format; 1079 PetscMPIInt size; 1080 1081 PetscFunctionBegin; 1082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1083 PetscValidType(mat, 1); 1084 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1085 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1086 PetscCheckSameComm(mat, 1, viewer, 2); 1087 1088 PetscCall(PetscViewerGetFormat(viewer, &format)); 1089 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1090 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1091 1092 #if !defined(PETSC_HAVE_THREADSAFETY) 1093 insidematview++; 1094 #endif 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1097 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1098 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1099 1100 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1101 if (isascii) { 1102 if (!mat->preallocated) { 1103 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1104 #if !defined(PETSC_HAVE_THREADSAFETY) 1105 insidematview--; 1106 #endif 1107 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1108 PetscFunctionReturn(PETSC_SUCCESS); 1109 } 1110 if (!mat->assembled) { 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1112 #if !defined(PETSC_HAVE_THREADSAFETY) 1113 insidematview--; 1114 #endif 1115 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1116 PetscFunctionReturn(PETSC_SUCCESS); 1117 } 1118 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1119 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1120 MatNullSpace nullsp, transnullsp; 1121 1122 PetscCall(PetscViewerASCIIPushTab(viewer)); 1123 PetscCall(MatGetSize(mat, &rows, &cols)); 1124 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1125 if (rbs != 1 || cbs != 1) { 1126 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1127 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1128 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1129 if (mat->factortype) { 1130 MatSolverType solver; 1131 PetscCall(MatFactorGetSolverType(mat, &solver)); 1132 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1133 } 1134 if (mat->ops->getinfo) { 1135 MatInfo info; 1136 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1137 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1138 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1139 } 1140 PetscCall(MatGetNullSpace(mat, &nullsp)); 1141 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1142 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1143 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1144 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1145 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscCall(MatProductView(mat, viewer)); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 } else if (issaws) { 1151 #if defined(PETSC_HAVE_SAWS) 1152 PetscMPIInt rank; 1153 1154 PetscCall(PetscObjectName((PetscObject)mat)); 1155 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1156 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1157 #endif 1158 } else if (isstring) { 1159 const char *type; 1160 PetscCall(MatGetType(mat, &type)); 1161 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1162 PetscTryTypeMethod(mat, view, viewer); 1163 } 1164 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1165 PetscCall(PetscViewerASCIIPushTab(viewer)); 1166 PetscUseTypeMethod(mat, viewnative, viewer); 1167 PetscCall(PetscViewerASCIIPopTab(viewer)); 1168 } else if (mat->ops->view) { 1169 PetscCall(PetscViewerASCIIPushTab(viewer)); 1170 PetscUseTypeMethod(mat, view, viewer); 1171 PetscCall(PetscViewerASCIIPopTab(viewer)); 1172 } 1173 if (isascii) { 1174 PetscCall(PetscViewerGetFormat(viewer, &format)); 1175 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1176 } 1177 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1178 #if !defined(PETSC_HAVE_THREADSAFETY) 1179 insidematview--; 1180 #endif 1181 PetscFunctionReturn(PETSC_SUCCESS); 1182 } 1183 1184 #if defined(PETSC_USE_DEBUG) 1185 #include <../src/sys/totalview/tv_data_display.h> 1186 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1187 { 1188 TV_add_row("Local rows", "int", &mat->rmap->n); 1189 TV_add_row("Local columns", "int", &mat->cmap->n); 1190 TV_add_row("Global rows", "int", &mat->rmap->N); 1191 TV_add_row("Global columns", "int", &mat->cmap->N); 1192 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1193 return TV_format_OK; 1194 } 1195 #endif 1196 1197 /*@C 1198 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1199 with `MatView()`. The matrix format is determined from the options database. 1200 Generates a parallel MPI matrix if the communicator has more than one 1201 processor. The default matrix type is `MATAIJ`. 1202 1203 Collective 1204 1205 Input Parameters: 1206 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1207 or some related function before a call to `MatLoad()` 1208 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1209 1210 Options Database Key: 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 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1311 1312 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1313 @*/ 1314 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1315 { 1316 PetscBool flg; 1317 1318 PetscFunctionBegin; 1319 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1320 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1321 1322 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1323 1324 flg = PETSC_FALSE; 1325 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1326 if (flg) { 1327 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1328 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1329 } 1330 flg = PETSC_FALSE; 1331 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1332 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1333 1334 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1335 PetscUseTypeMethod(mat, load, viewer); 1336 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1337 PetscFunctionReturn(PETSC_SUCCESS); 1338 } 1339 1340 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1341 { 1342 Mat_Redundant *redund = *redundant; 1343 1344 PetscFunctionBegin; 1345 if (redund) { 1346 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1347 PetscCall(ISDestroy(&redund->isrow)); 1348 PetscCall(ISDestroy(&redund->iscol)); 1349 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1350 } else { 1351 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1352 PetscCall(PetscFree(redund->sbuf_j)); 1353 PetscCall(PetscFree(redund->sbuf_a)); 1354 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1355 PetscCall(PetscFree(redund->rbuf_j[i])); 1356 PetscCall(PetscFree(redund->rbuf_a[i])); 1357 } 1358 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1359 } 1360 1361 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1362 PetscCall(PetscFree(redund)); 1363 } 1364 PetscFunctionReturn(PETSC_SUCCESS); 1365 } 1366 1367 /*@C 1368 MatDestroy - Frees space taken by a matrix. 1369 1370 Collective 1371 1372 Input Parameter: 1373 . A - the matrix 1374 1375 Level: beginner 1376 1377 Developer Note: 1378 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1379 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1380 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1381 if changes are needed here. 1382 1383 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1384 @*/ 1385 PetscErrorCode MatDestroy(Mat *A) 1386 { 1387 PetscFunctionBegin; 1388 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1389 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1390 if (--((PetscObject)(*A))->refct > 0) { 1391 *A = NULL; 1392 PetscFunctionReturn(PETSC_SUCCESS); 1393 } 1394 1395 /* if memory was published with SAWs then destroy it */ 1396 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1397 PetscTryTypeMethod(*A, destroy); 1398 1399 PetscCall(PetscFree((*A)->factorprefix)); 1400 PetscCall(PetscFree((*A)->defaultvectype)); 1401 PetscCall(PetscFree((*A)->defaultrandtype)); 1402 PetscCall(PetscFree((*A)->bsizes)); 1403 PetscCall(PetscFree((*A)->solvertype)); 1404 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1405 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1406 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1407 PetscCall(MatProductClear(*A)); 1408 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1409 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1410 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1411 PetscCall(MatDestroy(&(*A)->schur)); 1412 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1413 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1414 PetscCall(PetscHeaderDestroy(A)); 1415 PetscFunctionReturn(PETSC_SUCCESS); 1416 } 1417 1418 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1419 /*@C 1420 MatSetValues - Inserts or adds a block of values into a matrix. 1421 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1422 MUST be called after all calls to `MatSetValues()` have been completed. 1423 1424 Not Collective 1425 1426 Input Parameters: 1427 + mat - the matrix 1428 . v - a logically two-dimensional array of values 1429 . m - the number of rows 1430 . idxm - the global indices of the rows 1431 . n - the number of columns 1432 . idxn - the global indices of the columns 1433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1434 1435 Level: beginner 1436 1437 Notes: 1438 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1439 1440 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1441 options cannot be mixed without intervening calls to the assembly 1442 routines. 1443 1444 `MatSetValues()` uses 0-based row and column numbers in Fortran 1445 as well as in C. 1446 1447 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1448 simply ignored. This allows easily inserting element stiffness matrices 1449 with homogeneous Dirichlet boundary conditions that you don't want represented 1450 in the matrix. 1451 1452 Efficiency Alert: 1453 The routine `MatSetValuesBlocked()` may offer much better efficiency 1454 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1455 1456 Developer Note: 1457 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1458 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1459 1460 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1461 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1462 @*/ 1463 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1464 { 1465 PetscFunctionBeginHot; 1466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1467 PetscValidType(mat, 1); 1468 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1469 PetscAssertPointer(idxm, 3); 1470 PetscAssertPointer(idxn, 5); 1471 MatCheckPreallocated(mat, 1); 1472 1473 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1474 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1475 1476 if (PetscDefined(USE_DEBUG)) { 1477 PetscInt i, j; 1478 1479 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1480 for (i = 0; i < m; i++) { 1481 for (j = 0; j < n; j++) { 1482 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1483 #if defined(PETSC_USE_COMPLEX) 1484 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]); 1485 #else 1486 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]); 1487 #endif 1488 } 1489 } 1490 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); 1491 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); 1492 } 1493 1494 if (mat->assembled) { 1495 mat->was_assembled = PETSC_TRUE; 1496 mat->assembled = PETSC_FALSE; 1497 } 1498 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1499 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1500 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1501 PetscFunctionReturn(PETSC_SUCCESS); 1502 } 1503 1504 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1505 /*@C 1506 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1508 MUST be called after all calls to `MatSetValues()` have been completed. 1509 1510 Not Collective 1511 1512 Input Parameters: 1513 + mat - the matrix 1514 . v - a logically two-dimensional array of values 1515 . ism - the rows to provide 1516 . isn - the columns to provide 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirichlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 This is currently not optimized for any particular `ISType` 1541 1542 Developer Note: 1543 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1544 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1545 1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1547 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1548 @*/ 1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1550 { 1551 PetscInt m, n; 1552 const PetscInt *rows, *cols; 1553 1554 PetscFunctionBeginHot; 1555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1556 PetscCall(ISGetIndices(ism, &rows)); 1557 PetscCall(ISGetIndices(isn, &cols)); 1558 PetscCall(ISGetLocalSize(ism, &m)); 1559 PetscCall(ISGetLocalSize(isn, &n)); 1560 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1561 PetscCall(ISRestoreIndices(ism, &rows)); 1562 PetscCall(ISRestoreIndices(isn, &cols)); 1563 PetscFunctionReturn(PETSC_SUCCESS); 1564 } 1565 1566 /*@ 1567 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1568 values into a matrix 1569 1570 Not Collective 1571 1572 Input Parameters: 1573 + mat - the matrix 1574 . row - the (block) row to set 1575 - v - a logically two-dimensional array of values 1576 1577 Level: intermediate 1578 1579 Notes: 1580 The values, `v`, are column-oriented (for the block version) and sorted 1581 1582 All the nonzero values in `row` must be provided 1583 1584 The matrix must have previously had its column indices set, likely by having been assembled. 1585 1586 `row` must belong to this MPI process 1587 1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1589 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1590 @*/ 1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1592 { 1593 PetscInt globalrow; 1594 1595 PetscFunctionBegin; 1596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1597 PetscValidType(mat, 1); 1598 PetscAssertPointer(v, 3); 1599 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1600 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 /*@ 1605 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1606 values into a matrix 1607 1608 Not Collective 1609 1610 Input Parameters: 1611 + mat - the matrix 1612 . row - the (block) row to set 1613 - 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 1614 1615 Level: advanced 1616 1617 Notes: 1618 The values, `v`, are column-oriented for the block version. 1619 1620 All the nonzeros in `row` must be provided 1621 1622 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1623 1624 `row` must belong to this process 1625 1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1627 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1628 @*/ 1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1630 { 1631 PetscFunctionBeginHot; 1632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1633 PetscValidType(mat, 1); 1634 MatCheckPreallocated(mat, 1); 1635 PetscAssertPointer(v, 3); 1636 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1637 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1638 mat->insertmode = INSERT_VALUES; 1639 1640 if (mat->assembled) { 1641 mat->was_assembled = PETSC_TRUE; 1642 mat->assembled = PETSC_FALSE; 1643 } 1644 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1645 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1646 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1647 PetscFunctionReturn(PETSC_SUCCESS); 1648 } 1649 1650 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1651 /*@ 1652 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1653 Using structured grid indexing 1654 1655 Not Collective 1656 1657 Input Parameters: 1658 + mat - the matrix 1659 . m - number of rows being entered 1660 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1661 . n - number of columns being entered 1662 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1663 . v - a logically two-dimensional array of values 1664 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1665 1666 Level: beginner 1667 1668 Notes: 1669 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1670 1671 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1672 options cannot be mixed without intervening calls to the assembly 1673 routines. 1674 1675 The grid coordinates are across the entire grid, not just the local portion 1676 1677 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1678 as well as in C. 1679 1680 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1681 1682 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1683 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1684 1685 The columns and rows in the stencil passed in MUST be contained within the 1686 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1687 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1688 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1689 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1690 1691 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1692 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1693 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1694 `DM_BOUNDARY_PERIODIC` boundary type. 1695 1696 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 1697 a single value per point) you can skip filling those indices. 1698 1699 Inspired by the structured grid interface to the HYPRE package 1700 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1701 1702 Efficiency Alert: 1703 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1704 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1705 1706 Fortran Note: 1707 `idxm` and `idxn` should be declared as 1708 $ MatStencil idxm(4,m),idxn(4,n) 1709 and the values inserted using 1710 .vb 1711 idxm(MatStencil_i,1) = i 1712 idxm(MatStencil_j,1) = j 1713 idxm(MatStencil_k,1) = k 1714 idxm(MatStencil_c,1) = c 1715 etc 1716 .ve 1717 1718 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1719 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1720 @*/ 1721 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1722 { 1723 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1724 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1725 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1726 1727 PetscFunctionBegin; 1728 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1730 PetscValidType(mat, 1); 1731 PetscAssertPointer(idxm, 3); 1732 PetscAssertPointer(idxn, 5); 1733 1734 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1735 jdxm = buf; 1736 jdxn = buf + m; 1737 } else { 1738 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1739 jdxm = bufm; 1740 jdxn = bufn; 1741 } 1742 for (i = 0; i < m; i++) { 1743 for (j = 0; j < 3 - sdim; j++) dxm++; 1744 tmp = *dxm++ - starts[0]; 1745 for (j = 0; j < dim - 1; j++) { 1746 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1747 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1748 } 1749 if (mat->stencil.noc) dxm++; 1750 jdxm[i] = tmp; 1751 } 1752 for (i = 0; i < n; i++) { 1753 for (j = 0; j < 3 - sdim; j++) dxn++; 1754 tmp = *dxn++ - starts[0]; 1755 for (j = 0; j < dim - 1; j++) { 1756 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1757 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1758 } 1759 if (mat->stencil.noc) dxn++; 1760 jdxn[i] = tmp; 1761 } 1762 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1763 PetscCall(PetscFree2(bufm, bufn)); 1764 PetscFunctionReturn(PETSC_SUCCESS); 1765 } 1766 1767 /*@ 1768 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1769 Using structured grid indexing 1770 1771 Not Collective 1772 1773 Input Parameters: 1774 + mat - the matrix 1775 . m - number of rows being entered 1776 . idxm - grid coordinates for matrix rows being entered 1777 . n - number of columns being entered 1778 . idxn - grid coordinates for matrix columns being entered 1779 . v - a logically two-dimensional array of values 1780 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1781 1782 Level: beginner 1783 1784 Notes: 1785 By default the values, `v`, are row-oriented and unsorted. 1786 See `MatSetOption()` for other options. 1787 1788 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1789 options cannot be mixed without intervening calls to the assembly 1790 routines. 1791 1792 The grid coordinates are across the entire grid, not just the local portion 1793 1794 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1795 as well as in C. 1796 1797 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1798 1799 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1800 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1801 1802 The columns and rows in the stencil passed in MUST be contained within the 1803 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1804 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1805 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1806 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1807 1808 Negative indices may be passed in idxm and idxn, these rows and columns are 1809 simply ignored. This allows easily inserting element stiffness matrices 1810 with homogeneous Dirichlet boundary conditions that you don't want represented 1811 in the matrix. 1812 1813 Inspired by the structured grid interface to the HYPRE package 1814 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1815 1816 Fortran Note: 1817 `idxm` and `idxn` should be declared as 1818 $ MatStencil idxm(4,m),idxn(4,n) 1819 and the values inserted using 1820 .vb 1821 idxm(MatStencil_i,1) = i 1822 idxm(MatStencil_j,1) = j 1823 idxm(MatStencil_k,1) = k 1824 etc 1825 .ve 1826 1827 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1828 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1829 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1830 @*/ 1831 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1832 { 1833 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1834 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1835 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1836 1837 PetscFunctionBegin; 1838 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1840 PetscValidType(mat, 1); 1841 PetscAssertPointer(idxm, 3); 1842 PetscAssertPointer(idxn, 5); 1843 PetscAssertPointer(v, 6); 1844 1845 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1846 jdxm = buf; 1847 jdxn = buf + m; 1848 } else { 1849 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1850 jdxm = bufm; 1851 jdxn = bufn; 1852 } 1853 for (i = 0; i < m; i++) { 1854 for (j = 0; j < 3 - sdim; j++) dxm++; 1855 tmp = *dxm++ - starts[0]; 1856 for (j = 0; j < sdim - 1; j++) { 1857 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1858 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1859 } 1860 dxm++; 1861 jdxm[i] = tmp; 1862 } 1863 for (i = 0; i < n; i++) { 1864 for (j = 0; j < 3 - sdim; j++) dxn++; 1865 tmp = *dxn++ - starts[0]; 1866 for (j = 0; j < sdim - 1; j++) { 1867 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1868 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1869 } 1870 dxn++; 1871 jdxn[i] = tmp; 1872 } 1873 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1874 PetscCall(PetscFree2(bufm, bufn)); 1875 PetscFunctionReturn(PETSC_SUCCESS); 1876 } 1877 1878 /*@ 1879 MatSetStencil - Sets the grid information for setting values into a matrix via 1880 `MatSetValuesStencil()` 1881 1882 Not Collective 1883 1884 Input Parameters: 1885 + mat - the matrix 1886 . dim - dimension of the grid 1, 2, or 3 1887 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1888 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1889 - dof - number of degrees of freedom per node 1890 1891 Level: beginner 1892 1893 Notes: 1894 Inspired by the structured grid interface to the HYPRE package 1895 (www.llnl.gov/CASC/hyper) 1896 1897 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1898 user. 1899 1900 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1901 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1902 @*/ 1903 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1904 { 1905 PetscFunctionBegin; 1906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1907 PetscAssertPointer(dims, 3); 1908 PetscAssertPointer(starts, 4); 1909 1910 mat->stencil.dim = dim + (dof > 1); 1911 for (PetscInt i = 0; i < dim; i++) { 1912 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1913 mat->stencil.starts[i] = starts[dim - i - 1]; 1914 } 1915 mat->stencil.dims[dim] = dof; 1916 mat->stencil.starts[dim] = 0; 1917 mat->stencil.noc = (PetscBool)(dof == 1); 1918 PetscFunctionReturn(PETSC_SUCCESS); 1919 } 1920 1921 /*@C 1922 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1923 1924 Not Collective 1925 1926 Input Parameters: 1927 + mat - the matrix 1928 . v - a logically two-dimensional array of values 1929 . m - the number of block rows 1930 . idxm - the global block indices 1931 . n - the number of block columns 1932 . idxn - the global block indices 1933 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1934 1935 Level: intermediate 1936 1937 Notes: 1938 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1939 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1940 1941 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1942 NOT the total number of rows/columns; for example, if the block size is 2 and 1943 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1944 The values in idxm would be 1 2; that is the first index for each block divided by 1945 the block size. 1946 1947 You must call `MatSetBlockSize()` when constructing this matrix (before 1948 preallocating it). 1949 1950 By default the values, `v`, are row-oriented, so the layout of 1951 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1952 1953 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1954 options cannot be mixed without intervening calls to the assembly 1955 routines. 1956 1957 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1958 as well as in C. 1959 1960 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1961 simply ignored. This allows easily inserting element stiffness matrices 1962 with homogeneous Dirichlet boundary conditions that you don't want represented 1963 in the matrix. 1964 1965 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1966 internal searching must be done to determine where to place the 1967 data in the matrix storage space. By instead inserting blocks of 1968 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1969 reduced. 1970 1971 Example: 1972 .vb 1973 Suppose m=n=2 and block size(bs) = 2 The array is 1974 1975 1 2 | 3 4 1976 5 6 | 7 8 1977 - - - | - - - 1978 9 10 | 11 12 1979 13 14 | 15 16 1980 1981 v[] should be passed in like 1982 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1983 1984 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1985 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1986 .ve 1987 1988 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1989 @*/ 1990 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1991 { 1992 PetscFunctionBeginHot; 1993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1994 PetscValidType(mat, 1); 1995 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1996 PetscAssertPointer(idxm, 3); 1997 PetscAssertPointer(idxn, 5); 1998 MatCheckPreallocated(mat, 1); 1999 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2000 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2001 if (PetscDefined(USE_DEBUG)) { 2002 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2003 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2004 } 2005 if (PetscDefined(USE_DEBUG)) { 2006 PetscInt rbs, cbs, M, N, i; 2007 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2008 PetscCall(MatGetSize(mat, &M, &N)); 2009 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); 2010 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); 2011 } 2012 if (mat->assembled) { 2013 mat->was_assembled = PETSC_TRUE; 2014 mat->assembled = PETSC_FALSE; 2015 } 2016 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2017 if (mat->ops->setvaluesblocked) { 2018 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2019 } else { 2020 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2021 PetscInt i, j, bs, cbs; 2022 2023 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2024 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2025 iidxm = buf; 2026 iidxn = buf + m * bs; 2027 } else { 2028 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2029 iidxm = bufr; 2030 iidxn = bufc; 2031 } 2032 for (i = 0; i < m; i++) { 2033 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2034 } 2035 if (m != n || bs != cbs || idxm != idxn) { 2036 for (i = 0; i < n; i++) { 2037 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2038 } 2039 } else iidxn = iidxm; 2040 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2041 PetscCall(PetscFree2(bufr, bufc)); 2042 } 2043 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2044 PetscFunctionReturn(PETSC_SUCCESS); 2045 } 2046 2047 /*@C 2048 MatGetValues - Gets a block of local values from a matrix. 2049 2050 Not Collective; can only return values that are owned by the give process 2051 2052 Input Parameters: 2053 + mat - the matrix 2054 . v - a logically two-dimensional array for storing the values 2055 . m - the number of rows 2056 . idxm - the global indices of the rows 2057 . n - the number of columns 2058 - idxn - the global indices of the columns 2059 2060 Level: advanced 2061 2062 Notes: 2063 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2064 The values, `v`, are then returned in a row-oriented format, 2065 analogous to that used by default in `MatSetValues()`. 2066 2067 `MatGetValues()` uses 0-based row and column numbers in 2068 Fortran as well as in C. 2069 2070 `MatGetValues()` requires that the matrix has been assembled 2071 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2072 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2073 without intermediate matrix assembly. 2074 2075 Negative row or column indices will be ignored and those locations in `v` will be 2076 left unchanged. 2077 2078 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2079 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2080 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2081 2082 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2083 @*/ 2084 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2085 { 2086 PetscFunctionBegin; 2087 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2088 PetscValidType(mat, 1); 2089 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2090 PetscAssertPointer(idxm, 3); 2091 PetscAssertPointer(idxn, 5); 2092 PetscAssertPointer(v, 6); 2093 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2094 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2095 MatCheckPreallocated(mat, 1); 2096 2097 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2098 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2099 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2100 PetscFunctionReturn(PETSC_SUCCESS); 2101 } 2102 2103 /*@C 2104 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2105 defined previously by `MatSetLocalToGlobalMapping()` 2106 2107 Not Collective 2108 2109 Input Parameters: 2110 + mat - the matrix 2111 . nrow - number of rows 2112 . irow - the row local indices 2113 . ncol - number of columns 2114 - icol - the column local indices 2115 2116 Output Parameter: 2117 . y - a logically two-dimensional array of values 2118 2119 Level: advanced 2120 2121 Notes: 2122 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2123 2124 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, 2125 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2126 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2127 with `MatSetLocalToGlobalMapping()`. 2128 2129 Developer Note: 2130 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2131 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2132 2133 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2134 `MatSetValuesLocal()`, `MatGetValues()` 2135 @*/ 2136 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2137 { 2138 PetscFunctionBeginHot; 2139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2140 PetscValidType(mat, 1); 2141 MatCheckPreallocated(mat, 1); 2142 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2143 PetscAssertPointer(irow, 3); 2144 PetscAssertPointer(icol, 5); 2145 if (PetscDefined(USE_DEBUG)) { 2146 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2147 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2148 } 2149 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2150 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2151 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2152 else { 2153 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2154 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2155 irowm = buf; 2156 icolm = buf + nrow; 2157 } else { 2158 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2159 irowm = bufr; 2160 icolm = bufc; 2161 } 2162 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2163 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2164 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2165 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2166 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2167 PetscCall(PetscFree2(bufr, bufc)); 2168 } 2169 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2170 PetscFunctionReturn(PETSC_SUCCESS); 2171 } 2172 2173 /*@ 2174 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2175 the same size. Currently, this can only be called once and creates the given matrix. 2176 2177 Not Collective 2178 2179 Input Parameters: 2180 + mat - the matrix 2181 . nb - the number of blocks 2182 . bs - the number of rows (and columns) in each block 2183 . rows - a concatenation of the rows for each block 2184 - v - a concatenation of logically two-dimensional arrays of values 2185 2186 Level: advanced 2187 2188 Notes: 2189 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2190 2191 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2192 2193 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2194 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2195 @*/ 2196 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2197 { 2198 PetscFunctionBegin; 2199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2200 PetscValidType(mat, 1); 2201 PetscAssertPointer(rows, 4); 2202 PetscAssertPointer(v, 5); 2203 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2204 2205 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2206 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2207 else { 2208 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2209 } 2210 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2211 PetscFunctionReturn(PETSC_SUCCESS); 2212 } 2213 2214 /*@ 2215 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2216 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2217 using a local (per-processor) numbering. 2218 2219 Not Collective 2220 2221 Input Parameters: 2222 + x - the matrix 2223 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2224 - cmapping - column mapping 2225 2226 Level: intermediate 2227 2228 Note: 2229 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2230 2231 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2232 @*/ 2233 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2234 { 2235 PetscFunctionBegin; 2236 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2237 PetscValidType(x, 1); 2238 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2239 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2240 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2241 else { 2242 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2243 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2244 } 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /*@ 2249 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2250 2251 Not Collective 2252 2253 Input Parameter: 2254 . A - the matrix 2255 2256 Output Parameters: 2257 + rmapping - row mapping 2258 - cmapping - column mapping 2259 2260 Level: advanced 2261 2262 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2263 @*/ 2264 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2265 { 2266 PetscFunctionBegin; 2267 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2268 PetscValidType(A, 1); 2269 if (rmapping) { 2270 PetscAssertPointer(rmapping, 2); 2271 *rmapping = A->rmap->mapping; 2272 } 2273 if (cmapping) { 2274 PetscAssertPointer(cmapping, 3); 2275 *cmapping = A->cmap->mapping; 2276 } 2277 PetscFunctionReturn(PETSC_SUCCESS); 2278 } 2279 2280 /*@ 2281 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2282 2283 Logically Collective 2284 2285 Input Parameters: 2286 + A - the matrix 2287 . rmap - row layout 2288 - cmap - column layout 2289 2290 Level: advanced 2291 2292 Note: 2293 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2294 2295 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2296 @*/ 2297 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2298 { 2299 PetscFunctionBegin; 2300 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2301 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2302 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@ 2307 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2308 2309 Not Collective 2310 2311 Input Parameter: 2312 . A - the matrix 2313 2314 Output Parameters: 2315 + rmap - row layout 2316 - cmap - column layout 2317 2318 Level: advanced 2319 2320 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2321 @*/ 2322 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2323 { 2324 PetscFunctionBegin; 2325 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2326 PetscValidType(A, 1); 2327 if (rmap) { 2328 PetscAssertPointer(rmap, 2); 2329 *rmap = A->rmap; 2330 } 2331 if (cmap) { 2332 PetscAssertPointer(cmap, 3); 2333 *cmap = A->cmap; 2334 } 2335 PetscFunctionReturn(PETSC_SUCCESS); 2336 } 2337 2338 /*@C 2339 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2340 using a local numbering of the rows and columns. 2341 2342 Not Collective 2343 2344 Input Parameters: 2345 + mat - the matrix 2346 . nrow - number of rows 2347 . irow - the row local indices 2348 . ncol - number of columns 2349 . icol - the column local indices 2350 . y - a logically two-dimensional array of values 2351 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2352 2353 Level: intermediate 2354 2355 Notes: 2356 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2357 2358 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2359 options cannot be mixed without intervening calls to the assembly 2360 routines. 2361 2362 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2363 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2364 2365 Developer Note: 2366 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2367 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2368 2369 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2370 `MatGetValuesLocal()` 2371 @*/ 2372 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2373 { 2374 PetscFunctionBeginHot; 2375 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2376 PetscValidType(mat, 1); 2377 MatCheckPreallocated(mat, 1); 2378 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2379 PetscAssertPointer(irow, 3); 2380 PetscAssertPointer(icol, 5); 2381 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2382 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2383 if (PetscDefined(USE_DEBUG)) { 2384 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2385 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2386 } 2387 2388 if (mat->assembled) { 2389 mat->was_assembled = PETSC_TRUE; 2390 mat->assembled = PETSC_FALSE; 2391 } 2392 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2393 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2394 else { 2395 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2396 const PetscInt *irowm, *icolm; 2397 2398 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2399 bufr = buf; 2400 bufc = buf + nrow; 2401 irowm = bufr; 2402 icolm = bufc; 2403 } else { 2404 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2405 irowm = bufr; 2406 icolm = bufc; 2407 } 2408 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2409 else irowm = irow; 2410 if (mat->cmap->mapping) { 2411 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2412 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2413 } else icolm = irowm; 2414 } else icolm = icol; 2415 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2416 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2417 } 2418 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2419 PetscFunctionReturn(PETSC_SUCCESS); 2420 } 2421 2422 /*@C 2423 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2424 using a local ordering of the nodes a block at a time. 2425 2426 Not Collective 2427 2428 Input Parameters: 2429 + mat - the matrix 2430 . nrow - number of rows 2431 . irow - the row local indices 2432 . ncol - number of columns 2433 . icol - the column local indices 2434 . y - a logically two-dimensional array of values 2435 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2436 2437 Level: intermediate 2438 2439 Notes: 2440 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2441 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2442 2443 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2444 options cannot be mixed without intervening calls to the assembly 2445 routines. 2446 2447 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2448 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2449 2450 Developer Note: 2451 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2452 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2453 2454 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2455 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2456 @*/ 2457 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2458 { 2459 PetscFunctionBeginHot; 2460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2461 PetscValidType(mat, 1); 2462 MatCheckPreallocated(mat, 1); 2463 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2464 PetscAssertPointer(irow, 3); 2465 PetscAssertPointer(icol, 5); 2466 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2467 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2468 if (PetscDefined(USE_DEBUG)) { 2469 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2470 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); 2471 } 2472 2473 if (mat->assembled) { 2474 mat->was_assembled = PETSC_TRUE; 2475 mat->assembled = PETSC_FALSE; 2476 } 2477 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2478 PetscInt irbs, rbs; 2479 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2480 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2481 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2482 } 2483 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2484 PetscInt icbs, cbs; 2485 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2486 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2487 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2488 } 2489 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2490 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2491 else { 2492 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2493 const PetscInt *irowm, *icolm; 2494 2495 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2496 bufr = buf; 2497 bufc = buf + nrow; 2498 irowm = bufr; 2499 icolm = bufc; 2500 } else { 2501 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2502 irowm = bufr; 2503 icolm = bufc; 2504 } 2505 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2506 else irowm = irow; 2507 if (mat->cmap->mapping) { 2508 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2509 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2510 } else icolm = irowm; 2511 } else icolm = icol; 2512 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2513 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2514 } 2515 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2516 PetscFunctionReturn(PETSC_SUCCESS); 2517 } 2518 2519 /*@ 2520 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2521 2522 Collective 2523 2524 Input Parameters: 2525 + mat - the matrix 2526 - x - the vector to be multiplied 2527 2528 Output Parameter: 2529 . y - the result 2530 2531 Level: developer 2532 2533 Note: 2534 The vectors `x` and `y` cannot be the same. I.e., one cannot 2535 call `MatMultDiagonalBlock`(A,y,y). 2536 2537 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2538 @*/ 2539 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2540 { 2541 PetscFunctionBegin; 2542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2543 PetscValidType(mat, 1); 2544 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2545 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2546 2547 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2548 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2549 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2550 MatCheckPreallocated(mat, 1); 2551 2552 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2553 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2554 PetscFunctionReturn(PETSC_SUCCESS); 2555 } 2556 2557 /*@ 2558 MatMult - Computes the matrix-vector product, $y = Ax$. 2559 2560 Neighbor-wise Collective 2561 2562 Input Parameters: 2563 + mat - the matrix 2564 - x - the vector to be multiplied 2565 2566 Output Parameter: 2567 . y - the result 2568 2569 Level: beginner 2570 2571 Note: 2572 The vectors `x` and `y` cannot be the same. I.e., one cannot 2573 call `MatMult`(A,y,y). 2574 2575 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2576 @*/ 2577 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2578 { 2579 PetscFunctionBegin; 2580 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2581 PetscValidType(mat, 1); 2582 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2583 VecCheckAssembled(x); 2584 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2585 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2586 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2587 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2588 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); 2589 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); 2590 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); 2591 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); 2592 PetscCall(VecSetErrorIfLocked(y, 3)); 2593 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2594 MatCheckPreallocated(mat, 1); 2595 2596 PetscCall(VecLockReadPush(x)); 2597 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2598 PetscUseTypeMethod(mat, mult, x, y); 2599 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2600 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2601 PetscCall(VecLockReadPop(x)); 2602 PetscFunctionReturn(PETSC_SUCCESS); 2603 } 2604 2605 /*@ 2606 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2607 2608 Neighbor-wise Collective 2609 2610 Input Parameters: 2611 + mat - the matrix 2612 - x - the vector to be multiplied 2613 2614 Output Parameter: 2615 . y - the result 2616 2617 Level: beginner 2618 2619 Notes: 2620 The vectors `x` and `y` cannot be the same. I.e., one cannot 2621 call `MatMultTranspose`(A,y,y). 2622 2623 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2624 use `MatMultHermitianTranspose()` 2625 2626 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2627 @*/ 2628 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2629 { 2630 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2631 2632 PetscFunctionBegin; 2633 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2634 PetscValidType(mat, 1); 2635 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2636 VecCheckAssembled(x); 2637 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2638 2639 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2640 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2641 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2642 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); 2643 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); 2644 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); 2645 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); 2646 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2647 MatCheckPreallocated(mat, 1); 2648 2649 if (!mat->ops->multtranspose) { 2650 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2651 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); 2652 } else op = mat->ops->multtranspose; 2653 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2654 PetscCall(VecLockReadPush(x)); 2655 PetscCall((*op)(mat, x, y)); 2656 PetscCall(VecLockReadPop(x)); 2657 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2658 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2659 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2660 PetscFunctionReturn(PETSC_SUCCESS); 2661 } 2662 2663 /*@ 2664 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2665 2666 Neighbor-wise Collective 2667 2668 Input Parameters: 2669 + mat - the matrix 2670 - x - the vector to be multiplied 2671 2672 Output Parameter: 2673 . y - the result 2674 2675 Level: beginner 2676 2677 Notes: 2678 The vectors `x` and `y` cannot be the same. I.e., one cannot 2679 call `MatMultHermitianTranspose`(A,y,y). 2680 2681 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2682 2683 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2684 2685 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2686 @*/ 2687 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2688 { 2689 PetscFunctionBegin; 2690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2691 PetscValidType(mat, 1); 2692 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2693 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2694 2695 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2696 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2697 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2698 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); 2699 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); 2700 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); 2701 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); 2702 MatCheckPreallocated(mat, 1); 2703 2704 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2705 #if defined(PETSC_USE_COMPLEX) 2706 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2707 PetscCall(VecLockReadPush(x)); 2708 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2709 else PetscUseTypeMethod(mat, mult, x, y); 2710 PetscCall(VecLockReadPop(x)); 2711 } else { 2712 Vec w; 2713 PetscCall(VecDuplicate(x, &w)); 2714 PetscCall(VecCopy(x, w)); 2715 PetscCall(VecConjugate(w)); 2716 PetscCall(MatMultTranspose(mat, w, y)); 2717 PetscCall(VecDestroy(&w)); 2718 PetscCall(VecConjugate(y)); 2719 } 2720 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2721 #else 2722 PetscCall(MatMultTranspose(mat, x, y)); 2723 #endif 2724 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2725 PetscFunctionReturn(PETSC_SUCCESS); 2726 } 2727 2728 /*@ 2729 MatMultAdd - Computes $v3 = v2 + A * v1$. 2730 2731 Neighbor-wise Collective 2732 2733 Input Parameters: 2734 + mat - the matrix 2735 . v1 - the vector to be multiplied by `mat` 2736 - v2 - the vector to be added to the result 2737 2738 Output Parameter: 2739 . v3 - the result 2740 2741 Level: beginner 2742 2743 Note: 2744 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2745 call `MatMultAdd`(A,v1,v2,v1). 2746 2747 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2748 @*/ 2749 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2750 { 2751 PetscFunctionBegin; 2752 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2753 PetscValidType(mat, 1); 2754 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2755 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2756 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2757 2758 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2759 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2760 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); 2761 /* 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); 2762 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); */ 2763 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); 2764 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); 2765 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2766 MatCheckPreallocated(mat, 1); 2767 2768 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2769 PetscCall(VecLockReadPush(v1)); 2770 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2771 PetscCall(VecLockReadPop(v1)); 2772 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2773 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2774 PetscFunctionReturn(PETSC_SUCCESS); 2775 } 2776 2777 /*@ 2778 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2779 2780 Neighbor-wise Collective 2781 2782 Input Parameters: 2783 + mat - the matrix 2784 . v1 - the vector to be multiplied by the transpose of the matrix 2785 - v2 - the vector to be added to the result 2786 2787 Output Parameter: 2788 . v3 - the result 2789 2790 Level: beginner 2791 2792 Note: 2793 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2794 call `MatMultTransposeAdd`(A,v1,v2,v1). 2795 2796 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2797 @*/ 2798 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2799 { 2800 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2801 2802 PetscFunctionBegin; 2803 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2804 PetscValidType(mat, 1); 2805 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2806 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2807 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2808 2809 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2810 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2811 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); 2812 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); 2813 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); 2814 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2815 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2816 MatCheckPreallocated(mat, 1); 2817 2818 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2819 PetscCall(VecLockReadPush(v1)); 2820 PetscCall((*op)(mat, v1, v2, v3)); 2821 PetscCall(VecLockReadPop(v1)); 2822 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2823 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2824 PetscFunctionReturn(PETSC_SUCCESS); 2825 } 2826 2827 /*@ 2828 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2829 2830 Neighbor-wise Collective 2831 2832 Input Parameters: 2833 + mat - the matrix 2834 . v1 - the vector to be multiplied by the Hermitian transpose 2835 - v2 - the vector to be added to the result 2836 2837 Output Parameter: 2838 . v3 - the result 2839 2840 Level: beginner 2841 2842 Note: 2843 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2844 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2845 2846 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2847 @*/ 2848 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2849 { 2850 PetscFunctionBegin; 2851 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2852 PetscValidType(mat, 1); 2853 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2854 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2855 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2856 2857 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2858 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2859 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2860 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); 2861 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); 2862 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); 2863 MatCheckPreallocated(mat, 1); 2864 2865 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2866 PetscCall(VecLockReadPush(v1)); 2867 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2868 else { 2869 Vec w, z; 2870 PetscCall(VecDuplicate(v1, &w)); 2871 PetscCall(VecCopy(v1, w)); 2872 PetscCall(VecConjugate(w)); 2873 PetscCall(VecDuplicate(v3, &z)); 2874 PetscCall(MatMultTranspose(mat, w, z)); 2875 PetscCall(VecDestroy(&w)); 2876 PetscCall(VecConjugate(z)); 2877 if (v2 != v3) { 2878 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2879 } else { 2880 PetscCall(VecAXPY(v3, 1.0, z)); 2881 } 2882 PetscCall(VecDestroy(&z)); 2883 } 2884 PetscCall(VecLockReadPop(v1)); 2885 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2886 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@C 2891 MatGetFactorType - gets the type of factorization a matrix is 2892 2893 Not Collective 2894 2895 Input Parameter: 2896 . mat - the matrix 2897 2898 Output Parameter: 2899 . 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` 2900 2901 Level: intermediate 2902 2903 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2904 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2905 @*/ 2906 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2907 { 2908 PetscFunctionBegin; 2909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2910 PetscValidType(mat, 1); 2911 PetscAssertPointer(t, 2); 2912 *t = mat->factortype; 2913 PetscFunctionReturn(PETSC_SUCCESS); 2914 } 2915 2916 /*@C 2917 MatSetFactorType - sets the type of factorization a matrix is 2918 2919 Logically Collective 2920 2921 Input Parameters: 2922 + mat - the matrix 2923 - 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` 2924 2925 Level: intermediate 2926 2927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2928 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2929 @*/ 2930 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2931 { 2932 PetscFunctionBegin; 2933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2934 PetscValidType(mat, 1); 2935 mat->factortype = t; 2936 PetscFunctionReturn(PETSC_SUCCESS); 2937 } 2938 2939 /*@C 2940 MatGetInfo - Returns information about matrix storage (number of 2941 nonzeros, memory, etc.). 2942 2943 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2944 2945 Input Parameters: 2946 + mat - the matrix 2947 - 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) 2948 2949 Output Parameter: 2950 . info - matrix information context 2951 2952 Options Database Key: 2953 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2954 2955 Notes: 2956 The `MatInfo` context contains a variety of matrix data, including 2957 number of nonzeros allocated and used, number of mallocs during 2958 matrix assembly, etc. Additional information for factored matrices 2959 is provided (such as the fill ratio, number of mallocs during 2960 factorization, etc.). 2961 2962 Example: 2963 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2964 data within the MatInfo context. For example, 2965 .vb 2966 MatInfo info; 2967 Mat A; 2968 double mal, nz_a, nz_u; 2969 2970 MatGetInfo(A, MAT_LOCAL, &info); 2971 mal = info.mallocs; 2972 nz_a = info.nz_allocated; 2973 .ve 2974 2975 Fortran users should declare info as a double precision 2976 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2977 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2978 a complete list of parameter names. 2979 .vb 2980 double precision info(MAT_INFO_SIZE) 2981 double precision mal, nz_a 2982 Mat A 2983 integer ierr 2984 2985 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2986 mal = info(MAT_INFO_MALLOCS) 2987 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2988 .ve 2989 2990 Level: intermediate 2991 2992 Developer Note: 2993 The Fortran interface is not autogenerated as the 2994 interface definition cannot be generated correctly [due to `MatInfo` argument] 2995 2996 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2997 @*/ 2998 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2999 { 3000 PetscFunctionBegin; 3001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3002 PetscValidType(mat, 1); 3003 PetscAssertPointer(info, 3); 3004 MatCheckPreallocated(mat, 1); 3005 PetscUseTypeMethod(mat, getinfo, flag, info); 3006 PetscFunctionReturn(PETSC_SUCCESS); 3007 } 3008 3009 /* 3010 This is used by external packages where it is not easy to get the info from the actual 3011 matrix factorization. 3012 */ 3013 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3014 { 3015 PetscFunctionBegin; 3016 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3017 PetscFunctionReturn(PETSC_SUCCESS); 3018 } 3019 3020 /*@C 3021 MatLUFactor - Performs in-place LU factorization of matrix. 3022 3023 Collective 3024 3025 Input Parameters: 3026 + mat - the matrix 3027 . row - row permutation 3028 . col - column permutation 3029 - info - options for factorization, includes 3030 .vb 3031 fill - expected fill as ratio of original fill. 3032 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3033 Run with the option -info to determine an optimal value to use 3034 .ve 3035 3036 Level: developer 3037 3038 Notes: 3039 Most users should employ the `KSP` interface for linear solvers 3040 instead of working directly with matrix algebra routines such as this. 3041 See, e.g., `KSPCreate()`. 3042 3043 This changes the state of the matrix to a factored matrix; it cannot be used 3044 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3045 3046 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3047 when not using `KSP`. 3048 3049 Developer Note: 3050 The Fortran interface is not autogenerated as the 3051 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3052 3053 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3054 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3055 @*/ 3056 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3057 { 3058 MatFactorInfo tinfo; 3059 3060 PetscFunctionBegin; 3061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3062 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3063 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3064 if (info) PetscAssertPointer(info, 4); 3065 PetscValidType(mat, 1); 3066 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3067 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3068 MatCheckPreallocated(mat, 1); 3069 if (!info) { 3070 PetscCall(MatFactorInfoInitialize(&tinfo)); 3071 info = &tinfo; 3072 } 3073 3074 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3075 PetscUseTypeMethod(mat, lufactor, row, col, info); 3076 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3077 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3078 PetscFunctionReturn(PETSC_SUCCESS); 3079 } 3080 3081 /*@C 3082 MatILUFactor - Performs in-place ILU factorization of matrix. 3083 3084 Collective 3085 3086 Input Parameters: 3087 + mat - the matrix 3088 . row - row permutation 3089 . col - column permutation 3090 - info - structure containing 3091 .vb 3092 levels - number of levels of fill. 3093 expected fill - as ratio of original fill. 3094 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3095 missing diagonal entries) 3096 .ve 3097 3098 Level: developer 3099 3100 Notes: 3101 Most users should employ the `KSP` interface for linear solvers 3102 instead of working directly with matrix algebra routines such as this. 3103 See, e.g., `KSPCreate()`. 3104 3105 Probably really in-place only when level of fill is zero, otherwise allocates 3106 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3107 when not using `KSP`. 3108 3109 Developer Note: 3110 The Fortran interface is not autogenerated as the 3111 interface definition cannot be generated correctly [due to MatFactorInfo] 3112 3113 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3114 @*/ 3115 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3116 { 3117 PetscFunctionBegin; 3118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3119 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3120 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3121 PetscAssertPointer(info, 4); 3122 PetscValidType(mat, 1); 3123 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3124 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3125 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3126 MatCheckPreallocated(mat, 1); 3127 3128 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3129 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3130 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3131 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3132 PetscFunctionReturn(PETSC_SUCCESS); 3133 } 3134 3135 /*@C 3136 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3137 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3138 3139 Collective 3140 3141 Input Parameters: 3142 + fact - the factor matrix obtained with `MatGetFactor()` 3143 . mat - the matrix 3144 . row - the row permutation 3145 . col - the column permutation 3146 - info - options for factorization, includes 3147 .vb 3148 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3149 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3150 .ve 3151 3152 Level: developer 3153 3154 Notes: 3155 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3156 3157 Most users should employ the simplified `KSP` interface for linear solvers 3158 instead of working directly with matrix algebra routines such as this. 3159 See, e.g., `KSPCreate()`. 3160 3161 Developer Note: 3162 The Fortran interface is not autogenerated as the 3163 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3164 3165 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3166 @*/ 3167 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3168 { 3169 MatFactorInfo tinfo; 3170 3171 PetscFunctionBegin; 3172 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3174 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3175 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3176 if (info) PetscAssertPointer(info, 5); 3177 PetscValidType(fact, 1); 3178 PetscValidType(mat, 2); 3179 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3180 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3181 MatCheckPreallocated(mat, 2); 3182 if (!info) { 3183 PetscCall(MatFactorInfoInitialize(&tinfo)); 3184 info = &tinfo; 3185 } 3186 3187 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3188 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3189 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3190 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3191 PetscFunctionReturn(PETSC_SUCCESS); 3192 } 3193 3194 /*@C 3195 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3196 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3197 3198 Collective 3199 3200 Input Parameters: 3201 + fact - the factor matrix obtained with `MatGetFactor()` 3202 . mat - the matrix 3203 - info - options for factorization 3204 3205 Level: developer 3206 3207 Notes: 3208 See `MatLUFactor()` for in-place factorization. See 3209 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3210 3211 Most users should employ the `KSP` interface for linear solvers 3212 instead of working directly with matrix algebra routines such as this. 3213 See, e.g., `KSPCreate()`. 3214 3215 Developer Note: 3216 The Fortran interface is not autogenerated as the 3217 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3218 3219 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3220 @*/ 3221 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3222 { 3223 MatFactorInfo tinfo; 3224 3225 PetscFunctionBegin; 3226 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3227 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3228 PetscValidType(fact, 1); 3229 PetscValidType(mat, 2); 3230 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3231 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, 3232 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3233 3234 MatCheckPreallocated(mat, 2); 3235 if (!info) { 3236 PetscCall(MatFactorInfoInitialize(&tinfo)); 3237 info = &tinfo; 3238 } 3239 3240 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3241 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3242 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3243 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3244 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3245 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3246 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3247 PetscFunctionReturn(PETSC_SUCCESS); 3248 } 3249 3250 /*@C 3251 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3252 symmetric matrix. 3253 3254 Collective 3255 3256 Input Parameters: 3257 + mat - the matrix 3258 . perm - row and column permutations 3259 - info - expected fill as ratio of original fill 3260 3261 Level: developer 3262 3263 Notes: 3264 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3265 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3266 3267 Most users should employ the `KSP` interface for linear solvers 3268 instead of working directly with matrix algebra routines such as this. 3269 See, e.g., `KSPCreate()`. 3270 3271 Developer Note: 3272 The Fortran interface is not autogenerated as the 3273 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3274 3275 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3276 `MatGetOrdering()` 3277 @*/ 3278 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3279 { 3280 MatFactorInfo tinfo; 3281 3282 PetscFunctionBegin; 3283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3284 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3285 if (info) PetscAssertPointer(info, 3); 3286 PetscValidType(mat, 1); 3287 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3288 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3289 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3290 MatCheckPreallocated(mat, 1); 3291 if (!info) { 3292 PetscCall(MatFactorInfoInitialize(&tinfo)); 3293 info = &tinfo; 3294 } 3295 3296 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3297 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3298 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3299 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3300 PetscFunctionReturn(PETSC_SUCCESS); 3301 } 3302 3303 /*@C 3304 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3305 of a symmetric matrix. 3306 3307 Collective 3308 3309 Input Parameters: 3310 + fact - the factor matrix obtained with `MatGetFactor()` 3311 . mat - the matrix 3312 . perm - row and column permutations 3313 - info - options for factorization, includes 3314 .vb 3315 fill - expected fill as ratio of original fill. 3316 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3317 Run with the option -info to determine an optimal value to use 3318 .ve 3319 3320 Level: developer 3321 3322 Notes: 3323 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3324 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3325 3326 Most users should employ the `KSP` interface for linear solvers 3327 instead of working directly with matrix algebra routines such as this. 3328 See, e.g., `KSPCreate()`. 3329 3330 Developer Note: 3331 The Fortran interface is not autogenerated as the 3332 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3333 3334 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3335 `MatGetOrdering()` 3336 @*/ 3337 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3338 { 3339 MatFactorInfo tinfo; 3340 3341 PetscFunctionBegin; 3342 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3343 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3344 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3345 if (info) PetscAssertPointer(info, 4); 3346 PetscValidType(fact, 1); 3347 PetscValidType(mat, 2); 3348 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3349 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3350 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3351 MatCheckPreallocated(mat, 2); 3352 if (!info) { 3353 PetscCall(MatFactorInfoInitialize(&tinfo)); 3354 info = &tinfo; 3355 } 3356 3357 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3358 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3359 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3360 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3361 PetscFunctionReturn(PETSC_SUCCESS); 3362 } 3363 3364 /*@C 3365 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3366 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3367 `MatCholeskyFactorSymbolic()`. 3368 3369 Collective 3370 3371 Input Parameters: 3372 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3373 . mat - the initial matrix that is to be factored 3374 - info - options for factorization 3375 3376 Level: developer 3377 3378 Note: 3379 Most users should employ the `KSP` interface for linear solvers 3380 instead of working directly with matrix algebra routines such as this. 3381 See, e.g., `KSPCreate()`. 3382 3383 Developer Note: 3384 The Fortran interface is not autogenerated as the 3385 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3386 3387 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3388 @*/ 3389 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3390 { 3391 MatFactorInfo tinfo; 3392 3393 PetscFunctionBegin; 3394 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3396 PetscValidType(fact, 1); 3397 PetscValidType(mat, 2); 3398 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3399 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, 3400 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3401 MatCheckPreallocated(mat, 2); 3402 if (!info) { 3403 PetscCall(MatFactorInfoInitialize(&tinfo)); 3404 info = &tinfo; 3405 } 3406 3407 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3408 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3409 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3410 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3411 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3412 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3413 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3414 PetscFunctionReturn(PETSC_SUCCESS); 3415 } 3416 3417 /*@ 3418 MatQRFactor - Performs in-place QR factorization of matrix. 3419 3420 Collective 3421 3422 Input Parameters: 3423 + mat - the matrix 3424 . col - column permutation 3425 - info - options for factorization, includes 3426 .vb 3427 fill - expected fill as ratio of original fill. 3428 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3429 Run with the option -info to determine an optimal value to use 3430 .ve 3431 3432 Level: developer 3433 3434 Notes: 3435 Most users should employ the `KSP` interface for linear solvers 3436 instead of working directly with matrix algebra routines such as this. 3437 See, e.g., `KSPCreate()`. 3438 3439 This changes the state of the matrix to a factored matrix; it cannot be used 3440 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3441 3442 Developer Note: 3443 The Fortran interface is not autogenerated as the 3444 interface definition cannot be generated correctly [due to MatFactorInfo] 3445 3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3447 `MatSetUnfactored()` 3448 @*/ 3449 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3450 { 3451 PetscFunctionBegin; 3452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3453 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3454 if (info) PetscAssertPointer(info, 3); 3455 PetscValidType(mat, 1); 3456 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3457 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3458 MatCheckPreallocated(mat, 1); 3459 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3460 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3461 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3462 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3463 PetscFunctionReturn(PETSC_SUCCESS); 3464 } 3465 3466 /*@ 3467 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3468 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3469 3470 Collective 3471 3472 Input Parameters: 3473 + fact - the factor matrix obtained with `MatGetFactor()` 3474 . mat - the matrix 3475 . col - column permutation 3476 - info - options for factorization, includes 3477 .vb 3478 fill - expected fill as ratio of original fill. 3479 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3480 Run with the option -info to determine an optimal value to use 3481 .ve 3482 3483 Level: developer 3484 3485 Note: 3486 Most users should employ the `KSP` interface for linear solvers 3487 instead of working directly with matrix algebra routines such as this. 3488 See, e.g., `KSPCreate()`. 3489 3490 Developer Note: 3491 The Fortran interface is not autogenerated as the 3492 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3493 3494 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3495 @*/ 3496 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3497 { 3498 MatFactorInfo tinfo; 3499 3500 PetscFunctionBegin; 3501 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3502 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3503 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3504 if (info) PetscAssertPointer(info, 4); 3505 PetscValidType(fact, 1); 3506 PetscValidType(mat, 2); 3507 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3508 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3509 MatCheckPreallocated(mat, 2); 3510 if (!info) { 3511 PetscCall(MatFactorInfoInitialize(&tinfo)); 3512 info = &tinfo; 3513 } 3514 3515 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3516 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3517 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3518 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3519 PetscFunctionReturn(PETSC_SUCCESS); 3520 } 3521 3522 /*@ 3523 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3524 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3525 3526 Collective 3527 3528 Input Parameters: 3529 + fact - the factor matrix obtained with `MatGetFactor()` 3530 . mat - the matrix 3531 - info - options for factorization 3532 3533 Level: developer 3534 3535 Notes: 3536 See `MatQRFactor()` for in-place factorization. 3537 3538 Most users should employ the `KSP` interface for linear solvers 3539 instead of working directly with matrix algebra routines such as this. 3540 See, e.g., `KSPCreate()`. 3541 3542 Developer Note: 3543 The Fortran interface is not autogenerated as the 3544 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3545 3546 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3547 @*/ 3548 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3549 { 3550 MatFactorInfo tinfo; 3551 3552 PetscFunctionBegin; 3553 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3555 PetscValidType(fact, 1); 3556 PetscValidType(mat, 2); 3557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3558 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, 3559 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3560 3561 MatCheckPreallocated(mat, 2); 3562 if (!info) { 3563 PetscCall(MatFactorInfoInitialize(&tinfo)); 3564 info = &tinfo; 3565 } 3566 3567 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3568 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3569 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3570 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3571 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3572 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3573 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3574 PetscFunctionReturn(PETSC_SUCCESS); 3575 } 3576 3577 /*@ 3578 MatSolve - Solves $A x = b$, given a factored matrix. 3579 3580 Neighbor-wise Collective 3581 3582 Input Parameters: 3583 + mat - the factored matrix 3584 - b - the right-hand-side vector 3585 3586 Output Parameter: 3587 . x - the result vector 3588 3589 Level: developer 3590 3591 Notes: 3592 The vectors `b` and `x` cannot be the same. I.e., one cannot 3593 call `MatSolve`(A,x,x). 3594 3595 Most users should employ the `KSP` interface for linear solvers 3596 instead of working directly with matrix algebra routines such as this. 3597 See, e.g., `KSPCreate()`. 3598 3599 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3600 @*/ 3601 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3602 { 3603 PetscFunctionBegin; 3604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3605 PetscValidType(mat, 1); 3606 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3607 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3608 PetscCheckSameComm(mat, 1, b, 2); 3609 PetscCheckSameComm(mat, 1, x, 3); 3610 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3611 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); 3612 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); 3613 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); 3614 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3615 MatCheckPreallocated(mat, 1); 3616 3617 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3618 if (mat->factorerrortype) { 3619 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3620 PetscCall(VecSetInf(x)); 3621 } else PetscUseTypeMethod(mat, solve, b, x); 3622 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3623 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3624 PetscFunctionReturn(PETSC_SUCCESS); 3625 } 3626 3627 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3628 { 3629 Vec b, x; 3630 PetscInt N, i; 3631 PetscErrorCode (*f)(Mat, Vec, Vec); 3632 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3633 3634 PetscFunctionBegin; 3635 if (A->factorerrortype) { 3636 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3637 PetscCall(MatSetInf(X)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3641 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3642 PetscCall(MatBoundToCPU(A, &Abound)); 3643 if (!Abound) { 3644 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3645 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3646 } 3647 #if PetscDefined(HAVE_CUDA) 3648 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3649 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3650 #elif PetscDefined(HAVE_HIP) 3651 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3652 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3653 #endif 3654 PetscCall(MatGetSize(B, NULL, &N)); 3655 for (i = 0; i < N; i++) { 3656 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3657 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3658 PetscCall((*f)(A, b, x)); 3659 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3660 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3661 } 3662 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3663 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3664 PetscFunctionReturn(PETSC_SUCCESS); 3665 } 3666 3667 /*@ 3668 MatMatSolve - Solves $A X = B$, given a factored matrix. 3669 3670 Neighbor-wise Collective 3671 3672 Input Parameters: 3673 + A - the factored matrix 3674 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3675 3676 Output Parameter: 3677 . X - the result matrix (dense matrix) 3678 3679 Level: developer 3680 3681 Note: 3682 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3683 otherwise, `B` and `X` cannot be the same. 3684 3685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3686 @*/ 3687 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3688 { 3689 PetscFunctionBegin; 3690 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3691 PetscValidType(A, 1); 3692 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3693 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3694 PetscCheckSameComm(A, 1, B, 2); 3695 PetscCheckSameComm(A, 1, X, 3); 3696 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); 3697 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); 3698 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"); 3699 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3700 MatCheckPreallocated(A, 1); 3701 3702 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3703 if (!A->ops->matsolve) { 3704 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3705 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3706 } else PetscUseTypeMethod(A, matsolve, B, X); 3707 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3708 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3709 PetscFunctionReturn(PETSC_SUCCESS); 3710 } 3711 3712 /*@ 3713 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3714 3715 Neighbor-wise Collective 3716 3717 Input Parameters: 3718 + A - the factored matrix 3719 - B - the right-hand-side matrix (`MATDENSE` matrix) 3720 3721 Output Parameter: 3722 . X - the result matrix (dense matrix) 3723 3724 Level: developer 3725 3726 Note: 3727 The matrices `B` and `X` cannot be the same. I.e., one cannot 3728 call `MatMatSolveTranspose`(A,X,X). 3729 3730 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3731 @*/ 3732 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3733 { 3734 PetscFunctionBegin; 3735 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3736 PetscValidType(A, 1); 3737 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3738 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3739 PetscCheckSameComm(A, 1, B, 2); 3740 PetscCheckSameComm(A, 1, X, 3); 3741 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3742 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); 3743 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); 3744 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); 3745 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"); 3746 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3747 MatCheckPreallocated(A, 1); 3748 3749 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3750 if (!A->ops->matsolvetranspose) { 3751 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3752 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3753 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3754 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3755 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3756 PetscFunctionReturn(PETSC_SUCCESS); 3757 } 3758 3759 /*@ 3760 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3761 3762 Neighbor-wise Collective 3763 3764 Input Parameters: 3765 + A - the factored matrix 3766 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3767 3768 Output Parameter: 3769 . X - the result matrix (dense matrix) 3770 3771 Level: developer 3772 3773 Note: 3774 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 3775 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3776 3777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3778 @*/ 3779 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3780 { 3781 PetscFunctionBegin; 3782 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3783 PetscValidType(A, 1); 3784 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3785 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3786 PetscCheckSameComm(A, 1, Bt, 2); 3787 PetscCheckSameComm(A, 1, X, 3); 3788 3789 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3790 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); 3791 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); 3792 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"); 3793 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3794 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3795 MatCheckPreallocated(A, 1); 3796 3797 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3798 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3799 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3800 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3801 PetscFunctionReturn(PETSC_SUCCESS); 3802 } 3803 3804 /*@ 3805 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3806 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3807 3808 Neighbor-wise Collective 3809 3810 Input Parameters: 3811 + mat - the factored matrix 3812 - b - the right-hand-side vector 3813 3814 Output Parameter: 3815 . x - the result vector 3816 3817 Level: developer 3818 3819 Notes: 3820 `MatSolve()` should be used for most applications, as it performs 3821 a forward solve followed by a backward solve. 3822 3823 The vectors `b` and `x` cannot be the same, i.e., one cannot 3824 call `MatForwardSolve`(A,x,x). 3825 3826 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3827 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3828 `MatForwardSolve()` solves $U^T*D y = b$, and 3829 `MatBackwardSolve()` solves $U x = y$. 3830 Thus they do not provide a symmetric preconditioner. 3831 3832 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3833 @*/ 3834 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3835 { 3836 PetscFunctionBegin; 3837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3838 PetscValidType(mat, 1); 3839 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3840 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3841 PetscCheckSameComm(mat, 1, b, 2); 3842 PetscCheckSameComm(mat, 1, x, 3); 3843 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3844 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); 3845 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); 3846 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); 3847 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3848 MatCheckPreallocated(mat, 1); 3849 3850 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3851 PetscUseTypeMethod(mat, forwardsolve, b, x); 3852 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3853 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3854 PetscFunctionReturn(PETSC_SUCCESS); 3855 } 3856 3857 /*@ 3858 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3859 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3860 3861 Neighbor-wise Collective 3862 3863 Input Parameters: 3864 + mat - the factored matrix 3865 - b - the right-hand-side vector 3866 3867 Output Parameter: 3868 . x - the result vector 3869 3870 Level: developer 3871 3872 Notes: 3873 `MatSolve()` should be used for most applications, as it performs 3874 a forward solve followed by a backward solve. 3875 3876 The vectors `b` and `x` cannot be the same. I.e., one cannot 3877 call `MatBackwardSolve`(A,x,x). 3878 3879 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3880 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3881 `MatForwardSolve()` solves $U^T*D y = b$, and 3882 `MatBackwardSolve()` solves $U x = y$. 3883 Thus they do not provide a symmetric preconditioner. 3884 3885 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3886 @*/ 3887 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3888 { 3889 PetscFunctionBegin; 3890 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3891 PetscValidType(mat, 1); 3892 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3893 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3894 PetscCheckSameComm(mat, 1, b, 2); 3895 PetscCheckSameComm(mat, 1, x, 3); 3896 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3897 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); 3898 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); 3899 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); 3900 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3901 MatCheckPreallocated(mat, 1); 3902 3903 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3904 PetscUseTypeMethod(mat, backwardsolve, b, x); 3905 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3906 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3907 PetscFunctionReturn(PETSC_SUCCESS); 3908 } 3909 3910 /*@ 3911 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3912 3913 Neighbor-wise Collective 3914 3915 Input Parameters: 3916 + mat - the factored matrix 3917 . b - the right-hand-side vector 3918 - y - the vector to be added to 3919 3920 Output Parameter: 3921 . x - the result vector 3922 3923 Level: developer 3924 3925 Note: 3926 The vectors `b` and `x` cannot be the same. I.e., one cannot 3927 call `MatSolveAdd`(A,x,y,x). 3928 3929 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3930 @*/ 3931 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3932 { 3933 PetscScalar one = 1.0; 3934 Vec tmp; 3935 3936 PetscFunctionBegin; 3937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3938 PetscValidType(mat, 1); 3939 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3940 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3941 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3942 PetscCheckSameComm(mat, 1, b, 2); 3943 PetscCheckSameComm(mat, 1, y, 3); 3944 PetscCheckSameComm(mat, 1, x, 4); 3945 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3946 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); 3947 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); 3948 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); 3949 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); 3950 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); 3951 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3952 MatCheckPreallocated(mat, 1); 3953 3954 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3955 if (mat->factorerrortype) { 3956 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3957 PetscCall(VecSetInf(x)); 3958 } else if (mat->ops->solveadd) { 3959 PetscUseTypeMethod(mat, solveadd, b, y, x); 3960 } else { 3961 /* do the solve then the add manually */ 3962 if (x != y) { 3963 PetscCall(MatSolve(mat, b, x)); 3964 PetscCall(VecAXPY(x, one, y)); 3965 } else { 3966 PetscCall(VecDuplicate(x, &tmp)); 3967 PetscCall(VecCopy(x, tmp)); 3968 PetscCall(MatSolve(mat, b, x)); 3969 PetscCall(VecAXPY(x, one, tmp)); 3970 PetscCall(VecDestroy(&tmp)); 3971 } 3972 } 3973 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3974 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3975 PetscFunctionReturn(PETSC_SUCCESS); 3976 } 3977 3978 /*@ 3979 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 3980 3981 Neighbor-wise Collective 3982 3983 Input Parameters: 3984 + mat - the factored matrix 3985 - b - the right-hand-side vector 3986 3987 Output Parameter: 3988 . x - the result vector 3989 3990 Level: developer 3991 3992 Notes: 3993 The vectors `b` and `x` cannot be the same. I.e., one cannot 3994 call `MatSolveTranspose`(A,x,x). 3995 3996 Most users should employ the `KSP` interface for linear solvers 3997 instead of working directly with matrix algebra routines such as this. 3998 See, e.g., `KSPCreate()`. 3999 4000 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4001 @*/ 4002 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4003 { 4004 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4005 4006 PetscFunctionBegin; 4007 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4008 PetscValidType(mat, 1); 4009 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4010 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4011 PetscCheckSameComm(mat, 1, b, 2); 4012 PetscCheckSameComm(mat, 1, x, 3); 4013 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4014 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); 4015 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); 4016 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4017 MatCheckPreallocated(mat, 1); 4018 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4019 if (mat->factorerrortype) { 4020 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4021 PetscCall(VecSetInf(x)); 4022 } else { 4023 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4024 PetscCall((*f)(mat, b, x)); 4025 } 4026 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4027 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4028 PetscFunctionReturn(PETSC_SUCCESS); 4029 } 4030 4031 /*@ 4032 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4033 factored matrix. 4034 4035 Neighbor-wise Collective 4036 4037 Input Parameters: 4038 + mat - the factored matrix 4039 . b - the right-hand-side vector 4040 - y - the vector to be added to 4041 4042 Output Parameter: 4043 . x - the result vector 4044 4045 Level: developer 4046 4047 Note: 4048 The vectors `b` and `x` cannot be the same. I.e., one cannot 4049 call `MatSolveTransposeAdd`(A,x,y,x). 4050 4051 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4052 @*/ 4053 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4054 { 4055 PetscScalar one = 1.0; 4056 Vec tmp; 4057 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4058 4059 PetscFunctionBegin; 4060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4061 PetscValidType(mat, 1); 4062 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4063 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4064 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4065 PetscCheckSameComm(mat, 1, b, 2); 4066 PetscCheckSameComm(mat, 1, y, 3); 4067 PetscCheckSameComm(mat, 1, x, 4); 4068 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4069 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); 4070 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); 4071 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); 4072 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); 4073 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4074 MatCheckPreallocated(mat, 1); 4075 4076 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4077 if (mat->factorerrortype) { 4078 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4079 PetscCall(VecSetInf(x)); 4080 } else if (f) { 4081 PetscCall((*f)(mat, b, y, x)); 4082 } else { 4083 /* do the solve then the add manually */ 4084 if (x != y) { 4085 PetscCall(MatSolveTranspose(mat, b, x)); 4086 PetscCall(VecAXPY(x, one, y)); 4087 } else { 4088 PetscCall(VecDuplicate(x, &tmp)); 4089 PetscCall(VecCopy(x, tmp)); 4090 PetscCall(MatSolveTranspose(mat, b, x)); 4091 PetscCall(VecAXPY(x, one, tmp)); 4092 PetscCall(VecDestroy(&tmp)); 4093 } 4094 } 4095 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4096 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4097 PetscFunctionReturn(PETSC_SUCCESS); 4098 } 4099 4100 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4101 /*@ 4102 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4103 4104 Neighbor-wise Collective 4105 4106 Input Parameters: 4107 + mat - the matrix 4108 . b - the right hand side 4109 . omega - the relaxation factor 4110 . flag - flag indicating the type of SOR (see below) 4111 . shift - diagonal shift 4112 . its - the number of iterations 4113 - lits - the number of local iterations 4114 4115 Output Parameter: 4116 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4117 4118 SOR Flags: 4119 + `SOR_FORWARD_SWEEP` - forward SOR 4120 . `SOR_BACKWARD_SWEEP` - backward SOR 4121 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4122 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4123 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4124 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4125 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4126 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4127 upper/lower triangular part of matrix to 4128 vector (with omega) 4129 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4130 4131 Level: developer 4132 4133 Notes: 4134 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4135 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4136 on each processor. 4137 4138 Application programmers will not generally use `MatSOR()` directly, 4139 but instead will employ the `KSP`/`PC` interface. 4140 4141 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4142 4143 Most users should employ the `KSP` interface for linear solvers 4144 instead of working directly with matrix algebra routines such as this. 4145 See, e.g., `KSPCreate()`. 4146 4147 Vectors `x` and `b` CANNOT be the same 4148 4149 The flags are implemented as bitwise inclusive or operations. 4150 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4151 to specify a zero initial guess for SSOR. 4152 4153 Developer Note: 4154 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4155 4156 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4157 @*/ 4158 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4159 { 4160 PetscFunctionBegin; 4161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4162 PetscValidType(mat, 1); 4163 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4164 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4165 PetscCheckSameComm(mat, 1, b, 2); 4166 PetscCheckSameComm(mat, 1, x, 8); 4167 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4168 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4169 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); 4170 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); 4171 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); 4172 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4173 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4174 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4175 4176 MatCheckPreallocated(mat, 1); 4177 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4178 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4179 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4180 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4181 PetscFunctionReturn(PETSC_SUCCESS); 4182 } 4183 4184 /* 4185 Default matrix copy routine. 4186 */ 4187 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4188 { 4189 PetscInt i, rstart = 0, rend = 0, nz; 4190 const PetscInt *cwork; 4191 const PetscScalar *vwork; 4192 4193 PetscFunctionBegin; 4194 if (B->assembled) PetscCall(MatZeroEntries(B)); 4195 if (str == SAME_NONZERO_PATTERN) { 4196 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4197 for (i = rstart; i < rend; i++) { 4198 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4199 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4200 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4201 } 4202 } else { 4203 PetscCall(MatAYPX(B, 0.0, A, str)); 4204 } 4205 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4206 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4207 PetscFunctionReturn(PETSC_SUCCESS); 4208 } 4209 4210 /*@ 4211 MatCopy - Copies a matrix to another matrix. 4212 4213 Collective 4214 4215 Input Parameters: 4216 + A - the matrix 4217 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4218 4219 Output Parameter: 4220 . B - where the copy is put 4221 4222 Level: intermediate 4223 4224 Notes: 4225 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4226 4227 `MatCopy()` copies the matrix entries of a matrix to another existing 4228 matrix (after first zeroing the second matrix). A related routine is 4229 `MatConvert()`, which first creates a new matrix and then copies the data. 4230 4231 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4232 @*/ 4233 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4234 { 4235 PetscInt i; 4236 4237 PetscFunctionBegin; 4238 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4239 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4240 PetscValidType(A, 1); 4241 PetscValidType(B, 2); 4242 PetscCheckSameComm(A, 1, B, 2); 4243 MatCheckPreallocated(B, 2); 4244 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4245 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4246 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, 4247 A->cmap->N, B->cmap->N); 4248 MatCheckPreallocated(A, 1); 4249 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4250 4251 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4252 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4253 else PetscCall(MatCopy_Basic(A, B, str)); 4254 4255 B->stencil.dim = A->stencil.dim; 4256 B->stencil.noc = A->stencil.noc; 4257 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4258 B->stencil.dims[i] = A->stencil.dims[i]; 4259 B->stencil.starts[i] = A->stencil.starts[i]; 4260 } 4261 4262 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4263 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4264 PetscFunctionReturn(PETSC_SUCCESS); 4265 } 4266 4267 /*@C 4268 MatConvert - Converts a matrix to another matrix, either of the same 4269 or different type. 4270 4271 Collective 4272 4273 Input Parameters: 4274 + mat - the matrix 4275 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4276 same type as the original matrix. 4277 - reuse - denotes if the destination matrix is to be created or reused. 4278 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 4279 `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). 4280 4281 Output Parameter: 4282 . M - pointer to place new matrix 4283 4284 Level: intermediate 4285 4286 Notes: 4287 `MatConvert()` first creates a new matrix and then copies the data from 4288 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4289 entries of one matrix to another already existing matrix context. 4290 4291 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4292 the MPI communicator of the generated matrix is always the same as the communicator 4293 of the input matrix. 4294 4295 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4296 @*/ 4297 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4298 { 4299 PetscBool sametype, issame, flg; 4300 PetscBool3 issymmetric, ishermitian; 4301 char convname[256], mtype[256]; 4302 Mat B; 4303 4304 PetscFunctionBegin; 4305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4306 PetscValidType(mat, 1); 4307 PetscAssertPointer(M, 4); 4308 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4309 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4310 MatCheckPreallocated(mat, 1); 4311 4312 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4313 if (flg) newtype = mtype; 4314 4315 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4316 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4317 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4318 if (reuse == MAT_REUSE_MATRIX) { 4319 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4320 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4321 } 4322 4323 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4324 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4325 PetscFunctionReturn(PETSC_SUCCESS); 4326 } 4327 4328 /* Cache Mat options because some converters use MatHeaderReplace */ 4329 issymmetric = mat->symmetric; 4330 ishermitian = mat->hermitian; 4331 4332 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4333 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4334 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4335 } else { 4336 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4337 const char *prefix[3] = {"seq", "mpi", ""}; 4338 PetscInt i; 4339 /* 4340 Order of precedence: 4341 0) See if newtype is a superclass of the current matrix. 4342 1) See if a specialized converter is known to the current matrix. 4343 2) See if a specialized converter is known to the desired matrix class. 4344 3) See if a good general converter is registered for the desired class 4345 (as of 6/27/03 only MATMPIADJ falls into this category). 4346 4) See if a good general converter is known for the current matrix. 4347 5) Use a really basic converter. 4348 */ 4349 4350 /* 0) See if newtype is a superclass of the current matrix. 4351 i.e mat is mpiaij and newtype is aij */ 4352 for (i = 0; i < 2; i++) { 4353 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4354 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4355 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4356 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4357 if (flg) { 4358 if (reuse == MAT_INPLACE_MATRIX) { 4359 PetscCall(PetscInfo(mat, "Early return\n")); 4360 PetscFunctionReturn(PETSC_SUCCESS); 4361 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4362 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4363 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4364 PetscFunctionReturn(PETSC_SUCCESS); 4365 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4366 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4367 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4368 PetscFunctionReturn(PETSC_SUCCESS); 4369 } 4370 } 4371 } 4372 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4373 for (i = 0; i < 3; i++) { 4374 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4380 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4381 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4382 if (conv) goto foundconv; 4383 } 4384 4385 /* 2) See if a specialized converter is known to the desired matrix class. */ 4386 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4387 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4388 PetscCall(MatSetType(B, newtype)); 4389 for (i = 0; i < 3; i++) { 4390 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4391 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4392 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4394 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4395 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4396 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4397 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4398 if (conv) { 4399 PetscCall(MatDestroy(&B)); 4400 goto foundconv; 4401 } 4402 } 4403 4404 /* 3) See if a good general converter is registered for the desired class */ 4405 conv = B->ops->convertfrom; 4406 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4407 PetscCall(MatDestroy(&B)); 4408 if (conv) goto foundconv; 4409 4410 /* 4) See if a good general converter is known for the current matrix */ 4411 if (mat->ops->convert) conv = mat->ops->convert; 4412 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4413 if (conv) goto foundconv; 4414 4415 /* 5) Use a really basic converter. */ 4416 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4417 conv = MatConvert_Basic; 4418 4419 foundconv: 4420 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4421 PetscCall((*conv)(mat, newtype, reuse, M)); 4422 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4423 /* the block sizes must be same if the mappings are copied over */ 4424 (*M)->rmap->bs = mat->rmap->bs; 4425 (*M)->cmap->bs = mat->cmap->bs; 4426 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4427 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4428 (*M)->rmap->mapping = mat->rmap->mapping; 4429 (*M)->cmap->mapping = mat->cmap->mapping; 4430 } 4431 (*M)->stencil.dim = mat->stencil.dim; 4432 (*M)->stencil.noc = mat->stencil.noc; 4433 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4434 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4435 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4436 } 4437 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4438 } 4439 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4440 4441 /* Copy Mat options */ 4442 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4443 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4444 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4445 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4446 PetscFunctionReturn(PETSC_SUCCESS); 4447 } 4448 4449 /*@C 4450 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4451 4452 Not Collective 4453 4454 Input Parameter: 4455 . mat - the matrix, must be a factored matrix 4456 4457 Output Parameter: 4458 . type - the string name of the package (do not free this string) 4459 4460 Level: intermediate 4461 4462 Fortran Note: 4463 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4464 4465 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4466 @*/ 4467 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4468 { 4469 PetscErrorCode (*conv)(Mat, MatSolverType *); 4470 4471 PetscFunctionBegin; 4472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4473 PetscValidType(mat, 1); 4474 PetscAssertPointer(type, 2); 4475 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4476 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4477 if (conv) PetscCall((*conv)(mat, type)); 4478 else *type = MATSOLVERPETSC; 4479 PetscFunctionReturn(PETSC_SUCCESS); 4480 } 4481 4482 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4483 struct _MatSolverTypeForSpecifcType { 4484 MatType mtype; 4485 /* no entry for MAT_FACTOR_NONE */ 4486 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4487 MatSolverTypeForSpecifcType next; 4488 }; 4489 4490 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4491 struct _MatSolverTypeHolder { 4492 char *name; 4493 MatSolverTypeForSpecifcType handlers; 4494 MatSolverTypeHolder next; 4495 }; 4496 4497 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4498 4499 /*@C 4500 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4501 4502 Input Parameters: 4503 + package - name of the package, for example petsc or superlu 4504 . mtype - the matrix type that works with this package 4505 . ftype - the type of factorization supported by the package 4506 - createfactor - routine that will create the factored matrix ready to be used 4507 4508 Level: developer 4509 4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4511 `MatGetFactor()` 4512 @*/ 4513 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4514 { 4515 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4516 PetscBool flg; 4517 MatSolverTypeForSpecifcType inext, iprev = NULL; 4518 4519 PetscFunctionBegin; 4520 PetscCall(MatInitializePackage()); 4521 if (!next) { 4522 PetscCall(PetscNew(&MatSolverTypeHolders)); 4523 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4524 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4525 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4526 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4527 PetscFunctionReturn(PETSC_SUCCESS); 4528 } 4529 while (next) { 4530 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4531 if (flg) { 4532 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4533 inext = next->handlers; 4534 while (inext) { 4535 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4536 if (flg) { 4537 inext->createfactor[(int)ftype - 1] = createfactor; 4538 PetscFunctionReturn(PETSC_SUCCESS); 4539 } 4540 iprev = inext; 4541 inext = inext->next; 4542 } 4543 PetscCall(PetscNew(&iprev->next)); 4544 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4545 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4546 PetscFunctionReturn(PETSC_SUCCESS); 4547 } 4548 prev = next; 4549 next = next->next; 4550 } 4551 PetscCall(PetscNew(&prev->next)); 4552 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4553 PetscCall(PetscNew(&prev->next->handlers)); 4554 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4555 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4556 PetscFunctionReturn(PETSC_SUCCESS); 4557 } 4558 4559 /*@C 4560 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4561 4562 Input Parameters: 4563 + 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 4564 . ftype - the type of factorization supported by the type 4565 - mtype - the matrix type that works with this type 4566 4567 Output Parameters: 4568 + foundtype - `PETSC_TRUE` if the type was registered 4569 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4570 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4571 4572 Calling sequence of `createfactor`: 4573 + A - the matrix providing the factor matrix 4574 . mtype - the `MatType` of the factor requested 4575 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4576 4577 Level: developer 4578 4579 Note: 4580 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4581 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4582 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4583 4584 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4585 `MatInitializePackage()` 4586 @*/ 4587 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4588 { 4589 MatSolverTypeHolder next = MatSolverTypeHolders; 4590 PetscBool flg; 4591 MatSolverTypeForSpecifcType inext; 4592 4593 PetscFunctionBegin; 4594 if (foundtype) *foundtype = PETSC_FALSE; 4595 if (foundmtype) *foundmtype = PETSC_FALSE; 4596 if (createfactor) *createfactor = NULL; 4597 4598 if (type) { 4599 while (next) { 4600 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4601 if (flg) { 4602 if (foundtype) *foundtype = PETSC_TRUE; 4603 inext = next->handlers; 4604 while (inext) { 4605 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4606 if (flg) { 4607 if (foundmtype) *foundmtype = PETSC_TRUE; 4608 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4609 PetscFunctionReturn(PETSC_SUCCESS); 4610 } 4611 inext = inext->next; 4612 } 4613 } 4614 next = next->next; 4615 } 4616 } else { 4617 while (next) { 4618 inext = next->handlers; 4619 while (inext) { 4620 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4621 if (flg && inext->createfactor[(int)ftype - 1]) { 4622 if (foundtype) *foundtype = PETSC_TRUE; 4623 if (foundmtype) *foundmtype = PETSC_TRUE; 4624 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4625 PetscFunctionReturn(PETSC_SUCCESS); 4626 } 4627 inext = inext->next; 4628 } 4629 next = next->next; 4630 } 4631 /* try with base classes inext->mtype */ 4632 next = MatSolverTypeHolders; 4633 while (next) { 4634 inext = next->handlers; 4635 while (inext) { 4636 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4637 if (flg && inext->createfactor[(int)ftype - 1]) { 4638 if (foundtype) *foundtype = PETSC_TRUE; 4639 if (foundmtype) *foundmtype = PETSC_TRUE; 4640 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4641 PetscFunctionReturn(PETSC_SUCCESS); 4642 } 4643 inext = inext->next; 4644 } 4645 next = next->next; 4646 } 4647 } 4648 PetscFunctionReturn(PETSC_SUCCESS); 4649 } 4650 4651 PetscErrorCode MatSolverTypeDestroy(void) 4652 { 4653 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4654 MatSolverTypeForSpecifcType inext, iprev; 4655 4656 PetscFunctionBegin; 4657 while (next) { 4658 PetscCall(PetscFree(next->name)); 4659 inext = next->handlers; 4660 while (inext) { 4661 PetscCall(PetscFree(inext->mtype)); 4662 iprev = inext; 4663 inext = inext->next; 4664 PetscCall(PetscFree(iprev)); 4665 } 4666 prev = next; 4667 next = next->next; 4668 PetscCall(PetscFree(prev)); 4669 } 4670 MatSolverTypeHolders = NULL; 4671 PetscFunctionReturn(PETSC_SUCCESS); 4672 } 4673 4674 /*@C 4675 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4676 4677 Logically Collective 4678 4679 Input Parameter: 4680 . mat - the matrix 4681 4682 Output Parameter: 4683 . flg - `PETSC_TRUE` if uses the ordering 4684 4685 Level: developer 4686 4687 Note: 4688 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4689 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4690 4691 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4692 @*/ 4693 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4694 { 4695 PetscFunctionBegin; 4696 *flg = mat->canuseordering; 4697 PetscFunctionReturn(PETSC_SUCCESS); 4698 } 4699 4700 /*@C 4701 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4702 4703 Logically Collective 4704 4705 Input Parameters: 4706 + mat - the matrix obtained with `MatGetFactor()` 4707 - ftype - the factorization type to be used 4708 4709 Output Parameter: 4710 . otype - the preferred ordering type 4711 4712 Level: developer 4713 4714 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4715 @*/ 4716 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4717 { 4718 PetscFunctionBegin; 4719 *otype = mat->preferredordering[ftype]; 4720 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4721 PetscFunctionReturn(PETSC_SUCCESS); 4722 } 4723 4724 /*@C 4725 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4726 4727 Collective 4728 4729 Input Parameters: 4730 + mat - the matrix 4731 . 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 4732 the other criteria is returned 4733 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4734 4735 Output Parameter: 4736 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4737 4738 Options Database Keys: 4739 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4740 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4741 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4742 4743 Level: intermediate 4744 4745 Notes: 4746 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4747 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4748 4749 Users usually access the factorization solvers via `KSP` 4750 4751 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4752 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 4753 4754 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4755 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4756 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4757 4758 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4759 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4760 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4761 4762 Developer Note: 4763 This should actually be called `MatCreateFactor()` since it creates a new factor object 4764 4765 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4766 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4767 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4768 @*/ 4769 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4770 { 4771 PetscBool foundtype, foundmtype; 4772 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4773 4774 PetscFunctionBegin; 4775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4776 PetscValidType(mat, 1); 4777 4778 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4779 MatCheckPreallocated(mat, 1); 4780 4781 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4782 if (!foundtype) { 4783 if (type) { 4784 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], 4785 ((PetscObject)mat)->type_name, type); 4786 } else { 4787 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); 4788 } 4789 } 4790 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4791 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); 4792 4793 PetscCall((*conv)(mat, ftype, f)); 4794 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4795 PetscFunctionReturn(PETSC_SUCCESS); 4796 } 4797 4798 /*@C 4799 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4800 4801 Not Collective 4802 4803 Input Parameters: 4804 + mat - the matrix 4805 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4806 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4807 4808 Output Parameter: 4809 . flg - PETSC_TRUE if the factorization is available 4810 4811 Level: intermediate 4812 4813 Notes: 4814 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4815 such as pastix, superlu, mumps etc. 4816 4817 PETSc must have been ./configure to use the external solver, using the option --download-package 4818 4819 Developer Note: 4820 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4821 4822 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4823 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4824 @*/ 4825 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4826 { 4827 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4828 4829 PetscFunctionBegin; 4830 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4831 PetscAssertPointer(flg, 4); 4832 4833 *flg = PETSC_FALSE; 4834 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4835 4836 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4837 MatCheckPreallocated(mat, 1); 4838 4839 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4840 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4841 PetscFunctionReturn(PETSC_SUCCESS); 4842 } 4843 4844 /*@ 4845 MatDuplicate - Duplicates a matrix including the non-zero structure. 4846 4847 Collective 4848 4849 Input Parameters: 4850 + mat - the matrix 4851 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4852 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4853 4854 Output Parameter: 4855 . M - pointer to place new matrix 4856 4857 Level: intermediate 4858 4859 Notes: 4860 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4861 4862 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4863 4864 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. 4865 4866 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4867 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4868 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4869 4870 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4871 @*/ 4872 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4873 { 4874 Mat B; 4875 VecType vtype; 4876 PetscInt i; 4877 PetscObject dm, container_h, container_d; 4878 void (*viewf)(void); 4879 4880 PetscFunctionBegin; 4881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4882 PetscValidType(mat, 1); 4883 PetscAssertPointer(M, 3); 4884 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4885 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4886 MatCheckPreallocated(mat, 1); 4887 4888 *M = NULL; 4889 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4890 PetscUseTypeMethod(mat, duplicate, op, M); 4891 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4892 B = *M; 4893 4894 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4895 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4896 PetscCall(MatGetVecType(mat, &vtype)); 4897 PetscCall(MatSetVecType(B, vtype)); 4898 4899 B->stencil.dim = mat->stencil.dim; 4900 B->stencil.noc = mat->stencil.noc; 4901 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4902 B->stencil.dims[i] = mat->stencil.dims[i]; 4903 B->stencil.starts[i] = mat->stencil.starts[i]; 4904 } 4905 4906 B->nooffproczerorows = mat->nooffproczerorows; 4907 B->nooffprocentries = mat->nooffprocentries; 4908 4909 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4910 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4911 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4912 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4913 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4914 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4915 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4916 PetscFunctionReturn(PETSC_SUCCESS); 4917 } 4918 4919 /*@ 4920 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4921 4922 Logically Collective 4923 4924 Input Parameter: 4925 . mat - the matrix 4926 4927 Output Parameter: 4928 . v - the diagonal of the matrix 4929 4930 Level: intermediate 4931 4932 Note: 4933 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4934 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4935 is larger than `ndiag`, the values of the remaining entries are unspecified. 4936 4937 Currently only correct in parallel for square matrices. 4938 4939 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4940 @*/ 4941 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4942 { 4943 PetscFunctionBegin; 4944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4945 PetscValidType(mat, 1); 4946 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4947 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4948 MatCheckPreallocated(mat, 1); 4949 if (PetscDefined(USE_DEBUG)) { 4950 PetscInt nv, row, col, ndiag; 4951 4952 PetscCall(VecGetLocalSize(v, &nv)); 4953 PetscCall(MatGetLocalSize(mat, &row, &col)); 4954 ndiag = PetscMin(row, col); 4955 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); 4956 } 4957 4958 PetscUseTypeMethod(mat, getdiagonal, v); 4959 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4960 PetscFunctionReturn(PETSC_SUCCESS); 4961 } 4962 4963 /*@C 4964 MatGetRowMin - Gets the minimum value (of the real part) of each 4965 row of the matrix 4966 4967 Logically Collective 4968 4969 Input Parameter: 4970 . mat - the matrix 4971 4972 Output Parameters: 4973 + v - the vector for storing the maximums 4974 - idx - the indices of the column found for each row (optional) 4975 4976 Level: intermediate 4977 4978 Note: 4979 The result of this call are the same as if one converted the matrix to dense format 4980 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4981 4982 This code is only implemented for a couple of matrix formats. 4983 4984 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4985 `MatGetRowMax()` 4986 @*/ 4987 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4988 { 4989 PetscFunctionBegin; 4990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4991 PetscValidType(mat, 1); 4992 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4993 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4994 4995 if (!mat->cmap->N) { 4996 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4997 if (idx) { 4998 PetscInt i, m = mat->rmap->n; 4999 for (i = 0; i < m; i++) idx[i] = -1; 5000 } 5001 } else { 5002 MatCheckPreallocated(mat, 1); 5003 } 5004 PetscUseTypeMethod(mat, getrowmin, v, idx); 5005 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5006 PetscFunctionReturn(PETSC_SUCCESS); 5007 } 5008 5009 /*@C 5010 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5011 row of the matrix 5012 5013 Logically Collective 5014 5015 Input Parameter: 5016 . mat - the matrix 5017 5018 Output Parameters: 5019 + v - the vector for storing the minimums 5020 - idx - the indices of the column found for each row (or `NULL` if not needed) 5021 5022 Level: intermediate 5023 5024 Notes: 5025 if a row is completely empty or has only 0.0 values then the `idx` value for that 5026 row is 0 (the first column). 5027 5028 This code is only implemented for a couple of matrix formats. 5029 5030 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5031 @*/ 5032 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5033 { 5034 PetscFunctionBegin; 5035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5036 PetscValidType(mat, 1); 5037 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5039 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5040 5041 if (!mat->cmap->N) { 5042 PetscCall(VecSet(v, 0.0)); 5043 if (idx) { 5044 PetscInt i, m = mat->rmap->n; 5045 for (i = 0; i < m; i++) idx[i] = -1; 5046 } 5047 } else { 5048 MatCheckPreallocated(mat, 1); 5049 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5050 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5051 } 5052 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5053 PetscFunctionReturn(PETSC_SUCCESS); 5054 } 5055 5056 /*@C 5057 MatGetRowMax - Gets the maximum value (of the real part) of each 5058 row of the matrix 5059 5060 Logically Collective 5061 5062 Input Parameter: 5063 . mat - the matrix 5064 5065 Output Parameters: 5066 + v - the vector for storing the maximums 5067 - idx - the indices of the column found for each row (optional) 5068 5069 Level: intermediate 5070 5071 Notes: 5072 The result of this call are the same as if one converted the matrix to dense format 5073 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5074 5075 This code is only implemented for a couple of matrix formats. 5076 5077 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5078 @*/ 5079 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5080 { 5081 PetscFunctionBegin; 5082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5083 PetscValidType(mat, 1); 5084 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5085 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5086 5087 if (!mat->cmap->N) { 5088 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5089 if (idx) { 5090 PetscInt i, m = mat->rmap->n; 5091 for (i = 0; i < m; i++) idx[i] = -1; 5092 } 5093 } else { 5094 MatCheckPreallocated(mat, 1); 5095 PetscUseTypeMethod(mat, getrowmax, v, idx); 5096 } 5097 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5098 PetscFunctionReturn(PETSC_SUCCESS); 5099 } 5100 5101 /*@C 5102 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5103 row of the matrix 5104 5105 Logically Collective 5106 5107 Input Parameter: 5108 . mat - the matrix 5109 5110 Output Parameters: 5111 + v - the vector for storing the maximums 5112 - idx - the indices of the column found for each row (or `NULL` if not needed) 5113 5114 Level: intermediate 5115 5116 Notes: 5117 if a row is completely empty or has only 0.0 values then the `idx` value for that 5118 row is 0 (the first column). 5119 5120 This code is only implemented for a couple of matrix formats. 5121 5122 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5123 @*/ 5124 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5125 { 5126 PetscFunctionBegin; 5127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5128 PetscValidType(mat, 1); 5129 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5130 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5131 5132 if (!mat->cmap->N) { 5133 PetscCall(VecSet(v, 0.0)); 5134 if (idx) { 5135 PetscInt i, m = mat->rmap->n; 5136 for (i = 0; i < m; i++) idx[i] = -1; 5137 } 5138 } else { 5139 MatCheckPreallocated(mat, 1); 5140 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5141 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5142 } 5143 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5144 PetscFunctionReturn(PETSC_SUCCESS); 5145 } 5146 5147 /*@ 5148 MatGetRowSum - Gets the sum of each row of the matrix 5149 5150 Logically or Neighborhood Collective 5151 5152 Input Parameter: 5153 . mat - the matrix 5154 5155 Output Parameter: 5156 . v - the vector for storing the sum of rows 5157 5158 Level: intermediate 5159 5160 Note: 5161 This code is slow since it is not currently specialized for different formats 5162 5163 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5164 @*/ 5165 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5166 { 5167 Vec ones; 5168 5169 PetscFunctionBegin; 5170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5171 PetscValidType(mat, 1); 5172 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5173 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5174 MatCheckPreallocated(mat, 1); 5175 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5176 PetscCall(VecSet(ones, 1.)); 5177 PetscCall(MatMult(mat, ones, v)); 5178 PetscCall(VecDestroy(&ones)); 5179 PetscFunctionReturn(PETSC_SUCCESS); 5180 } 5181 5182 /*@ 5183 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5184 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5185 5186 Collective 5187 5188 Input Parameter: 5189 . mat - the matrix to provide the transpose 5190 5191 Output Parameter: 5192 . 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 5193 5194 Level: advanced 5195 5196 Note: 5197 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 5198 routine allows bypassing that call. 5199 5200 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5201 @*/ 5202 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5203 { 5204 PetscContainer rB = NULL; 5205 MatParentState *rb = NULL; 5206 5207 PetscFunctionBegin; 5208 PetscCall(PetscNew(&rb)); 5209 rb->id = ((PetscObject)mat)->id; 5210 rb->state = 0; 5211 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5212 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5213 PetscCall(PetscContainerSetPointer(rB, rb)); 5214 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5215 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5216 PetscCall(PetscObjectDereference((PetscObject)rB)); 5217 PetscFunctionReturn(PETSC_SUCCESS); 5218 } 5219 5220 /*@ 5221 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5222 5223 Collective 5224 5225 Input Parameters: 5226 + mat - the matrix to transpose 5227 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5228 5229 Output Parameter: 5230 . B - the transpose 5231 5232 Level: intermediate 5233 5234 Notes: 5235 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5236 5237 `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 5238 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5239 5240 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. 5241 5242 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5243 5244 If mat is unchanged from the last call this function returns immediately without recomputing the result 5245 5246 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5247 5248 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5249 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5250 @*/ 5251 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5252 { 5253 PetscContainer rB = NULL; 5254 MatParentState *rb = NULL; 5255 5256 PetscFunctionBegin; 5257 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5258 PetscValidType(mat, 1); 5259 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5260 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5261 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5262 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5263 MatCheckPreallocated(mat, 1); 5264 if (reuse == MAT_REUSE_MATRIX) { 5265 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5266 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5267 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5268 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5269 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5270 } 5271 5272 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5273 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5274 PetscUseTypeMethod(mat, transpose, reuse, B); 5275 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5276 } 5277 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5278 5279 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5280 if (reuse != MAT_INPLACE_MATRIX) { 5281 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5282 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5283 rb->state = ((PetscObject)mat)->state; 5284 rb->nonzerostate = mat->nonzerostate; 5285 } 5286 PetscFunctionReturn(PETSC_SUCCESS); 5287 } 5288 5289 /*@ 5290 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5291 5292 Collective 5293 5294 Input Parameter: 5295 . A - the matrix to transpose 5296 5297 Output Parameter: 5298 . 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 5299 numerical portion. 5300 5301 Level: intermediate 5302 5303 Note: 5304 This is not supported for many matrix types, use `MatTranspose()` in those cases 5305 5306 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5307 @*/ 5308 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5309 { 5310 PetscFunctionBegin; 5311 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5312 PetscValidType(A, 1); 5313 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5314 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5315 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5316 PetscUseTypeMethod(A, transposesymbolic, B); 5317 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5318 5319 PetscCall(MatTransposeSetPrecursor(A, *B)); 5320 PetscFunctionReturn(PETSC_SUCCESS); 5321 } 5322 5323 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5324 { 5325 PetscContainer rB; 5326 MatParentState *rb; 5327 5328 PetscFunctionBegin; 5329 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5330 PetscValidType(A, 1); 5331 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5332 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5333 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5334 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5335 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5336 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5337 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5338 PetscFunctionReturn(PETSC_SUCCESS); 5339 } 5340 5341 /*@ 5342 MatIsTranspose - Test whether a matrix is another one's transpose, 5343 or its own, in which case it tests symmetry. 5344 5345 Collective 5346 5347 Input Parameters: 5348 + A - the matrix to test 5349 . B - the matrix to test against, this can equal the first parameter 5350 - tol - tolerance, differences between entries smaller than this are counted as zero 5351 5352 Output Parameter: 5353 . flg - the result 5354 5355 Level: intermediate 5356 5357 Notes: 5358 Only available for `MATAIJ` matrices. 5359 5360 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5361 test involves parallel copies of the block off-diagonal parts of the matrix. 5362 5363 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5364 @*/ 5365 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5366 { 5367 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5368 5369 PetscFunctionBegin; 5370 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5371 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5372 PetscAssertPointer(flg, 4); 5373 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5374 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5375 *flg = PETSC_FALSE; 5376 if (f && g) { 5377 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5378 PetscCall((*f)(A, B, tol, flg)); 5379 } else { 5380 MatType mattype; 5381 5382 PetscCall(MatGetType(f ? B : A, &mattype)); 5383 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5384 } 5385 PetscFunctionReturn(PETSC_SUCCESS); 5386 } 5387 5388 /*@ 5389 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5390 5391 Collective 5392 5393 Input Parameters: 5394 + mat - the matrix to transpose and complex conjugate 5395 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5396 5397 Output Parameter: 5398 . B - the Hermitian transpose 5399 5400 Level: intermediate 5401 5402 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5403 @*/ 5404 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5405 { 5406 PetscFunctionBegin; 5407 PetscCall(MatTranspose(mat, reuse, B)); 5408 #if defined(PETSC_USE_COMPLEX) 5409 PetscCall(MatConjugate(*B)); 5410 #endif 5411 PetscFunctionReturn(PETSC_SUCCESS); 5412 } 5413 5414 /*@ 5415 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5416 5417 Collective 5418 5419 Input Parameters: 5420 + A - the matrix to test 5421 . B - the matrix to test against, this can equal the first parameter 5422 - tol - tolerance, differences between entries smaller than this are counted as zero 5423 5424 Output Parameter: 5425 . flg - the result 5426 5427 Level: intermediate 5428 5429 Notes: 5430 Only available for `MATAIJ` matrices. 5431 5432 The sequential algorithm 5433 has a running time of the order of the number of nonzeros; the parallel 5434 test involves parallel copies of the block off-diagonal parts of the matrix. 5435 5436 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5437 @*/ 5438 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5439 { 5440 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5441 5442 PetscFunctionBegin; 5443 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5444 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5445 PetscAssertPointer(flg, 4); 5446 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5447 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5448 if (f && g) { 5449 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5450 PetscCall((*f)(A, B, tol, flg)); 5451 } 5452 PetscFunctionReturn(PETSC_SUCCESS); 5453 } 5454 5455 /*@ 5456 MatPermute - Creates a new matrix with rows and columns permuted from the 5457 original. 5458 5459 Collective 5460 5461 Input Parameters: 5462 + mat - the matrix to permute 5463 . row - row permutation, each processor supplies only the permutation for its rows 5464 - col - column permutation, each processor supplies only the permutation for its columns 5465 5466 Output Parameter: 5467 . B - the permuted matrix 5468 5469 Level: advanced 5470 5471 Note: 5472 The index sets map from row/col of permuted matrix to row/col of original matrix. 5473 The index sets should be on the same communicator as mat and have the same local sizes. 5474 5475 Developer Note: 5476 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5477 exploit the fact that row and col are permutations, consider implementing the 5478 more general `MatCreateSubMatrix()` instead. 5479 5480 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5481 @*/ 5482 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5483 { 5484 PetscFunctionBegin; 5485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5486 PetscValidType(mat, 1); 5487 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5488 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5489 PetscAssertPointer(B, 4); 5490 PetscCheckSameComm(mat, 1, row, 2); 5491 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5492 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5493 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5494 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5495 MatCheckPreallocated(mat, 1); 5496 5497 if (mat->ops->permute) { 5498 PetscUseTypeMethod(mat, permute, row, col, B); 5499 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5500 } else { 5501 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5502 } 5503 PetscFunctionReturn(PETSC_SUCCESS); 5504 } 5505 5506 /*@ 5507 MatEqual - Compares two matrices. 5508 5509 Collective 5510 5511 Input Parameters: 5512 + A - the first matrix 5513 - B - the second matrix 5514 5515 Output Parameter: 5516 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5517 5518 Level: intermediate 5519 5520 .seealso: [](ch_matrices), `Mat` 5521 @*/ 5522 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5523 { 5524 PetscFunctionBegin; 5525 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5526 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5527 PetscValidType(A, 1); 5528 PetscValidType(B, 2); 5529 PetscAssertPointer(flg, 3); 5530 PetscCheckSameComm(A, 1, B, 2); 5531 MatCheckPreallocated(A, 1); 5532 MatCheckPreallocated(B, 2); 5533 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5534 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5535 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, 5536 B->cmap->N); 5537 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5538 PetscUseTypeMethod(A, equal, B, flg); 5539 } else { 5540 PetscCall(MatMultEqual(A, B, 10, flg)); 5541 } 5542 PetscFunctionReturn(PETSC_SUCCESS); 5543 } 5544 5545 /*@ 5546 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5547 matrices that are stored as vectors. Either of the two scaling 5548 matrices can be `NULL`. 5549 5550 Collective 5551 5552 Input Parameters: 5553 + mat - the matrix to be scaled 5554 . l - the left scaling vector (or `NULL`) 5555 - r - the right scaling vector (or `NULL`) 5556 5557 Level: intermediate 5558 5559 Note: 5560 `MatDiagonalScale()` computes $A = LAR$, where 5561 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5562 The L scales the rows of the matrix, the R scales the columns of the matrix. 5563 5564 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5565 @*/ 5566 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5567 { 5568 PetscFunctionBegin; 5569 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5570 PetscValidType(mat, 1); 5571 if (l) { 5572 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5573 PetscCheckSameComm(mat, 1, l, 2); 5574 } 5575 if (r) { 5576 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5577 PetscCheckSameComm(mat, 1, r, 3); 5578 } 5579 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5580 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5581 MatCheckPreallocated(mat, 1); 5582 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5583 5584 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5585 PetscUseTypeMethod(mat, diagonalscale, l, r); 5586 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5587 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5588 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5589 PetscFunctionReturn(PETSC_SUCCESS); 5590 } 5591 5592 /*@ 5593 MatScale - Scales all elements of a matrix by a given number. 5594 5595 Logically Collective 5596 5597 Input Parameters: 5598 + mat - the matrix to be scaled 5599 - a - the scaling value 5600 5601 Level: intermediate 5602 5603 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5604 @*/ 5605 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5606 { 5607 PetscFunctionBegin; 5608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5609 PetscValidType(mat, 1); 5610 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5611 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5612 PetscValidLogicalCollectiveScalar(mat, a, 2); 5613 MatCheckPreallocated(mat, 1); 5614 5615 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5616 if (a != (PetscScalar)1.0) { 5617 PetscUseTypeMethod(mat, scale, a); 5618 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5619 } 5620 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5621 PetscFunctionReturn(PETSC_SUCCESS); 5622 } 5623 5624 /*@ 5625 MatNorm - Calculates various norms of a matrix. 5626 5627 Collective 5628 5629 Input Parameters: 5630 + mat - the matrix 5631 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5632 5633 Output Parameter: 5634 . nrm - the resulting norm 5635 5636 Level: intermediate 5637 5638 .seealso: [](ch_matrices), `Mat` 5639 @*/ 5640 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5641 { 5642 PetscFunctionBegin; 5643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5644 PetscValidType(mat, 1); 5645 PetscAssertPointer(nrm, 3); 5646 5647 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5648 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5649 MatCheckPreallocated(mat, 1); 5650 5651 PetscUseTypeMethod(mat, norm, type, nrm); 5652 PetscFunctionReturn(PETSC_SUCCESS); 5653 } 5654 5655 /* 5656 This variable is used to prevent counting of MatAssemblyBegin() that 5657 are called from within a MatAssemblyEnd(). 5658 */ 5659 static PetscInt MatAssemblyEnd_InUse = 0; 5660 /*@ 5661 MatAssemblyBegin - Begins assembling the matrix. This routine should 5662 be called after completing all calls to `MatSetValues()`. 5663 5664 Collective 5665 5666 Input Parameters: 5667 + mat - the matrix 5668 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5669 5670 Level: beginner 5671 5672 Notes: 5673 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5674 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5675 5676 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5677 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5678 using the matrix. 5679 5680 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5681 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 5682 a global collective operation requiring all processes that share the matrix. 5683 5684 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5685 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5686 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5687 5688 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5689 @*/ 5690 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5691 { 5692 PetscFunctionBegin; 5693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5694 PetscValidType(mat, 1); 5695 MatCheckPreallocated(mat, 1); 5696 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5697 if (mat->assembled) { 5698 mat->was_assembled = PETSC_TRUE; 5699 mat->assembled = PETSC_FALSE; 5700 } 5701 5702 if (!MatAssemblyEnd_InUse) { 5703 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5704 PetscTryTypeMethod(mat, assemblybegin, type); 5705 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5706 } else PetscTryTypeMethod(mat, assemblybegin, type); 5707 PetscFunctionReturn(PETSC_SUCCESS); 5708 } 5709 5710 /*@ 5711 MatAssembled - Indicates if a matrix has been assembled and is ready for 5712 use; for example, in matrix-vector product. 5713 5714 Not Collective 5715 5716 Input Parameter: 5717 . mat - the matrix 5718 5719 Output Parameter: 5720 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5721 5722 Level: advanced 5723 5724 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5725 @*/ 5726 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5727 { 5728 PetscFunctionBegin; 5729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5730 PetscAssertPointer(assembled, 2); 5731 *assembled = mat->assembled; 5732 PetscFunctionReturn(PETSC_SUCCESS); 5733 } 5734 5735 /*@ 5736 MatAssemblyEnd - Completes assembling the matrix. This routine should 5737 be called after `MatAssemblyBegin()`. 5738 5739 Collective 5740 5741 Input Parameters: 5742 + mat - the matrix 5743 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5744 5745 Options Database Keys: 5746 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5747 . -mat_view ::ascii_info_detail - Prints more detailed info 5748 . -mat_view - Prints matrix in ASCII format 5749 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5750 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5751 . -display <name> - Sets display name (default is host) 5752 . -draw_pause <sec> - Sets number of seconds to pause after display 5753 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5754 . -viewer_socket_machine <machine> - Machine to use for socket 5755 . -viewer_socket_port <port> - Port number to use for socket 5756 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5757 5758 Level: beginner 5759 5760 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5761 @*/ 5762 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5763 { 5764 static PetscInt inassm = 0; 5765 PetscBool flg = PETSC_FALSE; 5766 5767 PetscFunctionBegin; 5768 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5769 PetscValidType(mat, 1); 5770 5771 inassm++; 5772 MatAssemblyEnd_InUse++; 5773 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5774 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5775 PetscTryTypeMethod(mat, assemblyend, type); 5776 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5777 } else PetscTryTypeMethod(mat, assemblyend, type); 5778 5779 /* Flush assembly is not a true assembly */ 5780 if (type != MAT_FLUSH_ASSEMBLY) { 5781 if (mat->num_ass) { 5782 if (!mat->symmetry_eternal) { 5783 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5784 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5785 } 5786 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5787 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5788 } 5789 mat->num_ass++; 5790 mat->assembled = PETSC_TRUE; 5791 mat->ass_nonzerostate = mat->nonzerostate; 5792 } 5793 5794 mat->insertmode = NOT_SET_VALUES; 5795 MatAssemblyEnd_InUse--; 5796 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5797 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5798 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5799 5800 if (mat->checksymmetryonassembly) { 5801 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5802 if (flg) { 5803 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5804 } else { 5805 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5806 } 5807 } 5808 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5809 } 5810 inassm--; 5811 PetscFunctionReturn(PETSC_SUCCESS); 5812 } 5813 5814 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5815 /*@ 5816 MatSetOption - Sets a parameter option for a matrix. Some options 5817 may be specific to certain storage formats. Some options 5818 determine how values will be inserted (or added). Sorted, 5819 row-oriented input will generally assemble the fastest. The default 5820 is row-oriented. 5821 5822 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5823 5824 Input Parameters: 5825 + mat - the matrix 5826 . op - the option, one of those listed below (and possibly others), 5827 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5828 5829 Options Describing Matrix Structure: 5830 + `MAT_SPD` - symmetric positive definite 5831 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5832 . `MAT_HERMITIAN` - transpose is the complex conjugation 5833 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5834 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5835 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5836 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5837 5838 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5839 do not need to be computed (usually at a high cost) 5840 5841 Options For Use with `MatSetValues()`: 5842 Insert a logically dense subblock, which can be 5843 . `MAT_ROW_ORIENTED` - row-oriented (default) 5844 5845 These options reflect the data you pass in with `MatSetValues()`; it has 5846 nothing to do with how the data is stored internally in the matrix 5847 data structure. 5848 5849 When (re)assembling a matrix, we can restrict the input for 5850 efficiency/debugging purposes. These options include 5851 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5852 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5853 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5854 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5855 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5856 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5857 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5858 performance for very large process counts. 5859 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5860 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5861 functions, instead sending only neighbor messages. 5862 5863 Level: intermediate 5864 5865 Notes: 5866 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5867 5868 Some options are relevant only for particular matrix types and 5869 are thus ignored by others. Other options are not supported by 5870 certain matrix types and will generate an error message if set. 5871 5872 If using Fortran to compute a matrix, one may need to 5873 use the column-oriented option (or convert to the row-oriented 5874 format). 5875 5876 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5877 that would generate a new entry in the nonzero structure is instead 5878 ignored. Thus, if memory has not already been allocated for this particular 5879 data, then the insertion is ignored. For dense matrices, in which 5880 the entire array is allocated, no entries are ever ignored. 5881 Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5882 5883 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5884 that would generate a new entry in the nonzero structure instead produces 5885 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 5886 5887 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5888 that would generate a new entry that has not been preallocated will 5889 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5890 only.) This is a useful flag when debugging matrix memory preallocation. 5891 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5892 5893 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5894 other processors should be dropped, rather than stashed. 5895 This is useful if you know that the "owning" processor is also 5896 always generating the correct matrix entries, so that PETSc need 5897 not transfer duplicate entries generated on another processor. 5898 5899 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5900 searches during matrix assembly. When this flag is set, the hash table 5901 is created during the first matrix assembly. This hash table is 5902 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5903 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5904 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5905 supported by `MATMPIBAIJ` format only. 5906 5907 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5908 are kept in the nonzero structure 5909 5910 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5911 a zero location in the matrix 5912 5913 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5914 5915 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5916 zero row routines and thus improves performance for very large process counts. 5917 5918 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5919 part of the matrix (since they should match the upper triangular part). 5920 5921 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5922 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5923 with finite difference schemes with non-periodic boundary conditions. 5924 5925 Developer Note: 5926 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5927 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 5928 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5929 not changed. 5930 5931 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5932 @*/ 5933 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5934 { 5935 PetscFunctionBegin; 5936 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5937 if (op > 0) { 5938 PetscValidLogicalCollectiveEnum(mat, op, 2); 5939 PetscValidLogicalCollectiveBool(mat, flg, 3); 5940 } 5941 5942 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); 5943 5944 switch (op) { 5945 case MAT_FORCE_DIAGONAL_ENTRIES: 5946 mat->force_diagonals = flg; 5947 PetscFunctionReturn(PETSC_SUCCESS); 5948 case MAT_NO_OFF_PROC_ENTRIES: 5949 mat->nooffprocentries = flg; 5950 PetscFunctionReturn(PETSC_SUCCESS); 5951 case MAT_SUBSET_OFF_PROC_ENTRIES: 5952 mat->assembly_subset = flg; 5953 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5954 #if !defined(PETSC_HAVE_MPIUNI) 5955 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5956 #endif 5957 mat->stash.first_assembly_done = PETSC_FALSE; 5958 } 5959 PetscFunctionReturn(PETSC_SUCCESS); 5960 case MAT_NO_OFF_PROC_ZERO_ROWS: 5961 mat->nooffproczerorows = flg; 5962 PetscFunctionReturn(PETSC_SUCCESS); 5963 case MAT_SPD: 5964 if (flg) { 5965 mat->spd = PETSC_BOOL3_TRUE; 5966 mat->symmetric = PETSC_BOOL3_TRUE; 5967 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5968 } else { 5969 mat->spd = PETSC_BOOL3_FALSE; 5970 } 5971 break; 5972 case MAT_SYMMETRIC: 5973 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5974 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5975 #if !defined(PETSC_USE_COMPLEX) 5976 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5977 #endif 5978 break; 5979 case MAT_HERMITIAN: 5980 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5981 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5982 #if !defined(PETSC_USE_COMPLEX) 5983 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5984 #endif 5985 break; 5986 case MAT_STRUCTURALLY_SYMMETRIC: 5987 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5988 break; 5989 case MAT_SYMMETRY_ETERNAL: 5990 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"); 5991 mat->symmetry_eternal = flg; 5992 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5993 break; 5994 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5995 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"); 5996 mat->structural_symmetry_eternal = flg; 5997 break; 5998 case MAT_SPD_ETERNAL: 5999 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"); 6000 mat->spd_eternal = flg; 6001 if (flg) { 6002 mat->structural_symmetry_eternal = PETSC_TRUE; 6003 mat->symmetry_eternal = PETSC_TRUE; 6004 } 6005 break; 6006 case MAT_STRUCTURE_ONLY: 6007 mat->structure_only = flg; 6008 break; 6009 case MAT_SORTED_FULL: 6010 mat->sortedfull = flg; 6011 break; 6012 default: 6013 break; 6014 } 6015 PetscTryTypeMethod(mat, setoption, op, flg); 6016 PetscFunctionReturn(PETSC_SUCCESS); 6017 } 6018 6019 /*@ 6020 MatGetOption - Gets a parameter option that has been set for a matrix. 6021 6022 Logically Collective 6023 6024 Input Parameters: 6025 + mat - the matrix 6026 - op - the option, this only responds to certain options, check the code for which ones 6027 6028 Output Parameter: 6029 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6030 6031 Level: intermediate 6032 6033 Notes: 6034 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6035 6036 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6037 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6038 6039 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6040 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6041 @*/ 6042 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6043 { 6044 PetscFunctionBegin; 6045 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6046 PetscValidType(mat, 1); 6047 6048 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); 6049 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()"); 6050 6051 switch (op) { 6052 case MAT_NO_OFF_PROC_ENTRIES: 6053 *flg = mat->nooffprocentries; 6054 break; 6055 case MAT_NO_OFF_PROC_ZERO_ROWS: 6056 *flg = mat->nooffproczerorows; 6057 break; 6058 case MAT_SYMMETRIC: 6059 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6060 break; 6061 case MAT_HERMITIAN: 6062 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6063 break; 6064 case MAT_STRUCTURALLY_SYMMETRIC: 6065 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6066 break; 6067 case MAT_SPD: 6068 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6069 break; 6070 case MAT_SYMMETRY_ETERNAL: 6071 *flg = mat->symmetry_eternal; 6072 break; 6073 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6074 *flg = mat->symmetry_eternal; 6075 break; 6076 default: 6077 break; 6078 } 6079 PetscFunctionReturn(PETSC_SUCCESS); 6080 } 6081 6082 /*@ 6083 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6084 this routine retains the old nonzero structure. 6085 6086 Logically Collective 6087 6088 Input Parameter: 6089 . mat - the matrix 6090 6091 Level: intermediate 6092 6093 Note: 6094 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. 6095 See the Performance chapter of the users manual for information on preallocating matrices. 6096 6097 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6098 @*/ 6099 PetscErrorCode MatZeroEntries(Mat mat) 6100 { 6101 PetscFunctionBegin; 6102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6103 PetscValidType(mat, 1); 6104 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6105 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"); 6106 MatCheckPreallocated(mat, 1); 6107 6108 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6109 PetscUseTypeMethod(mat, zeroentries); 6110 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6111 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6112 PetscFunctionReturn(PETSC_SUCCESS); 6113 } 6114 6115 /*@ 6116 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6117 of a set of rows and columns of a matrix. 6118 6119 Collective 6120 6121 Input Parameters: 6122 + mat - the matrix 6123 . numRows - the number of rows/columns to zero 6124 . rows - the global row indices 6125 . diag - value put in the diagonal of the eliminated rows 6126 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6127 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6128 6129 Level: intermediate 6130 6131 Notes: 6132 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6133 6134 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6135 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 6136 6137 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6138 Krylov method to take advantage of the known solution on the zeroed rows. 6139 6140 For the parallel case, all processes that share the matrix (i.e., 6141 those in the communicator used for matrix creation) MUST call this 6142 routine, regardless of whether any rows being zeroed are owned by 6143 them. 6144 6145 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6146 6147 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6148 list only rows local to itself). 6149 6150 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6151 6152 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6153 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6154 @*/ 6155 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6156 { 6157 PetscFunctionBegin; 6158 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6159 PetscValidType(mat, 1); 6160 if (numRows) PetscAssertPointer(rows, 3); 6161 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6162 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6163 MatCheckPreallocated(mat, 1); 6164 6165 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6166 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6167 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6168 PetscFunctionReturn(PETSC_SUCCESS); 6169 } 6170 6171 /*@ 6172 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6173 of a set of rows and columns of a matrix. 6174 6175 Collective 6176 6177 Input Parameters: 6178 + mat - the matrix 6179 . is - the rows to zero 6180 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6181 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6182 - b - optional vector of right hand side, that will be adjusted by provided solution 6183 6184 Level: intermediate 6185 6186 Note: 6187 See `MatZeroRowsColumns()` for details on how this routine operates. 6188 6189 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6190 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6191 @*/ 6192 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6193 { 6194 PetscInt numRows; 6195 const PetscInt *rows; 6196 6197 PetscFunctionBegin; 6198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6199 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6200 PetscValidType(mat, 1); 6201 PetscValidType(is, 2); 6202 PetscCall(ISGetLocalSize(is, &numRows)); 6203 PetscCall(ISGetIndices(is, &rows)); 6204 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6205 PetscCall(ISRestoreIndices(is, &rows)); 6206 PetscFunctionReturn(PETSC_SUCCESS); 6207 } 6208 6209 /*@ 6210 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6211 of a set of rows of a matrix. 6212 6213 Collective 6214 6215 Input Parameters: 6216 + mat - the matrix 6217 . numRows - the number of rows to zero 6218 . rows - the global row indices 6219 . diag - value put in the diagonal of the zeroed rows 6220 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6221 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6222 6223 Level: intermediate 6224 6225 Notes: 6226 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6227 6228 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6229 6230 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6231 Krylov method to take advantage of the known solution on the zeroed rows. 6232 6233 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) 6234 from the matrix. 6235 6236 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6237 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 6238 formats this does not alter the nonzero structure. 6239 6240 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6241 of the matrix is not changed the values are 6242 merely zeroed. 6243 6244 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6245 formats can optionally remove the main diagonal entry from the 6246 nonzero structure as well, by passing 0.0 as the final argument). 6247 6248 For the parallel case, all processes that share the matrix (i.e., 6249 those in the communicator used for matrix creation) MUST call this 6250 routine, regardless of whether any rows being zeroed are owned by 6251 them. 6252 6253 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6254 list only rows local to itself). 6255 6256 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6257 owns that are to be zeroed. This saves a global synchronization in the implementation. 6258 6259 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6260 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6261 @*/ 6262 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6263 { 6264 PetscFunctionBegin; 6265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6266 PetscValidType(mat, 1); 6267 if (numRows) PetscAssertPointer(rows, 3); 6268 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6269 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6270 MatCheckPreallocated(mat, 1); 6271 6272 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6273 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6274 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6275 PetscFunctionReturn(PETSC_SUCCESS); 6276 } 6277 6278 /*@ 6279 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6280 of a set of rows of a matrix. 6281 6282 Collective 6283 6284 Input Parameters: 6285 + mat - the matrix 6286 . is - index set of rows to remove (if `NULL` then no row is removed) 6287 . diag - value put in all diagonals of eliminated rows 6288 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6289 - b - optional vector of right hand side, that will be adjusted by provided solution 6290 6291 Level: intermediate 6292 6293 Note: 6294 See `MatZeroRows()` for details on how this routine operates. 6295 6296 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6297 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6298 @*/ 6299 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6300 { 6301 PetscInt numRows = 0; 6302 const PetscInt *rows = NULL; 6303 6304 PetscFunctionBegin; 6305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6306 PetscValidType(mat, 1); 6307 if (is) { 6308 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6309 PetscCall(ISGetLocalSize(is, &numRows)); 6310 PetscCall(ISGetIndices(is, &rows)); 6311 } 6312 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6313 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6314 PetscFunctionReturn(PETSC_SUCCESS); 6315 } 6316 6317 /*@ 6318 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6319 of a set of rows of a matrix. These rows must be local to the process. 6320 6321 Collective 6322 6323 Input Parameters: 6324 + mat - the matrix 6325 . numRows - the number of rows to remove 6326 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6327 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6328 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6329 - b - optional vector of right hand side, that will be adjusted by provided solution 6330 6331 Level: intermediate 6332 6333 Notes: 6334 See `MatZeroRows()` for details on how this routine operates. 6335 6336 The grid coordinates are across the entire grid, not just the local portion 6337 6338 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6339 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6340 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6341 `DM_BOUNDARY_PERIODIC` boundary type. 6342 6343 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 6344 a single value per point) you can skip filling those indices. 6345 6346 Fortran Note: 6347 `idxm` and `idxn` should be declared as 6348 $ MatStencil idxm(4, m) 6349 and the values inserted using 6350 .vb 6351 idxm(MatStencil_i, 1) = i 6352 idxm(MatStencil_j, 1) = j 6353 idxm(MatStencil_k, 1) = k 6354 idxm(MatStencil_c, 1) = c 6355 etc 6356 .ve 6357 6358 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6359 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6360 @*/ 6361 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6362 { 6363 PetscInt dim = mat->stencil.dim; 6364 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6365 PetscInt *dims = mat->stencil.dims + 1; 6366 PetscInt *starts = mat->stencil.starts; 6367 PetscInt *dxm = (PetscInt *)rows; 6368 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6369 6370 PetscFunctionBegin; 6371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6372 PetscValidType(mat, 1); 6373 if (numRows) PetscAssertPointer(rows, 3); 6374 6375 PetscCall(PetscMalloc1(numRows, &jdxm)); 6376 for (i = 0; i < numRows; ++i) { 6377 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6378 for (j = 0; j < 3 - sdim; ++j) dxm++; 6379 /* Local index in X dir */ 6380 tmp = *dxm++ - starts[0]; 6381 /* Loop over remaining dimensions */ 6382 for (j = 0; j < dim - 1; ++j) { 6383 /* If nonlocal, set index to be negative */ 6384 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6385 /* Update local index */ 6386 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6387 } 6388 /* Skip component slot if necessary */ 6389 if (mat->stencil.noc) dxm++; 6390 /* Local row number */ 6391 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6392 } 6393 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6394 PetscCall(PetscFree(jdxm)); 6395 PetscFunctionReturn(PETSC_SUCCESS); 6396 } 6397 6398 /*@ 6399 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6400 of a set of rows and columns of a matrix. 6401 6402 Collective 6403 6404 Input Parameters: 6405 + mat - the matrix 6406 . numRows - the number of rows/columns to remove 6407 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6408 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6409 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6410 - b - optional vector of right hand side, that will be adjusted by provided solution 6411 6412 Level: intermediate 6413 6414 Notes: 6415 See `MatZeroRowsColumns()` for details on how this routine operates. 6416 6417 The grid coordinates are across the entire grid, not just the local portion 6418 6419 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6420 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6421 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6422 `DM_BOUNDARY_PERIODIC` boundary type. 6423 6424 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 6425 a single value per point) you can skip filling those indices. 6426 6427 Fortran Note: 6428 `idxm` and `idxn` should be declared as 6429 $ MatStencil idxm(4, m) 6430 and the values inserted using 6431 .vb 6432 idxm(MatStencil_i, 1) = i 6433 idxm(MatStencil_j, 1) = j 6434 idxm(MatStencil_k, 1) = k 6435 idxm(MatStencil_c, 1) = c 6436 etc 6437 .ve 6438 6439 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6440 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6441 @*/ 6442 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6443 { 6444 PetscInt dim = mat->stencil.dim; 6445 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6446 PetscInt *dims = mat->stencil.dims + 1; 6447 PetscInt *starts = mat->stencil.starts; 6448 PetscInt *dxm = (PetscInt *)rows; 6449 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6450 6451 PetscFunctionBegin; 6452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6453 PetscValidType(mat, 1); 6454 if (numRows) PetscAssertPointer(rows, 3); 6455 6456 PetscCall(PetscMalloc1(numRows, &jdxm)); 6457 for (i = 0; i < numRows; ++i) { 6458 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6459 for (j = 0; j < 3 - sdim; ++j) dxm++; 6460 /* Local index in X dir */ 6461 tmp = *dxm++ - starts[0]; 6462 /* Loop over remaining dimensions */ 6463 for (j = 0; j < dim - 1; ++j) { 6464 /* If nonlocal, set index to be negative */ 6465 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6466 /* Update local index */ 6467 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6468 } 6469 /* Skip component slot if necessary */ 6470 if (mat->stencil.noc) dxm++; 6471 /* Local row number */ 6472 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6473 } 6474 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6475 PetscCall(PetscFree(jdxm)); 6476 PetscFunctionReturn(PETSC_SUCCESS); 6477 } 6478 6479 /*@C 6480 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6481 of a set of rows of a matrix; using local numbering of rows. 6482 6483 Collective 6484 6485 Input Parameters: 6486 + mat - the matrix 6487 . numRows - the number of rows to remove 6488 . rows - the local row indices 6489 . diag - value put in all diagonals of eliminated rows 6490 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6491 - b - optional vector of right hand side, that will be adjusted by provided solution 6492 6493 Level: intermediate 6494 6495 Notes: 6496 Before calling `MatZeroRowsLocal()`, the user must first set the 6497 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6498 6499 See `MatZeroRows()` for details on how this routine operates. 6500 6501 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6502 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6503 @*/ 6504 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6505 { 6506 PetscFunctionBegin; 6507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6508 PetscValidType(mat, 1); 6509 if (numRows) PetscAssertPointer(rows, 3); 6510 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6511 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6512 MatCheckPreallocated(mat, 1); 6513 6514 if (mat->ops->zerorowslocal) { 6515 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6516 } else { 6517 IS is, newis; 6518 const PetscInt *newRows; 6519 6520 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6521 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6522 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6523 PetscCall(ISGetIndices(newis, &newRows)); 6524 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6525 PetscCall(ISRestoreIndices(newis, &newRows)); 6526 PetscCall(ISDestroy(&newis)); 6527 PetscCall(ISDestroy(&is)); 6528 } 6529 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6530 PetscFunctionReturn(PETSC_SUCCESS); 6531 } 6532 6533 /*@ 6534 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6535 of a set of rows of a matrix; using local numbering of rows. 6536 6537 Collective 6538 6539 Input Parameters: 6540 + mat - the matrix 6541 . is - index set of rows to remove 6542 . diag - value put in all diagonals of eliminated rows 6543 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6544 - b - optional vector of right hand side, that will be adjusted by provided solution 6545 6546 Level: intermediate 6547 6548 Notes: 6549 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6550 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6551 6552 See `MatZeroRows()` for details on how this routine operates. 6553 6554 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6555 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6556 @*/ 6557 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6558 { 6559 PetscInt numRows; 6560 const PetscInt *rows; 6561 6562 PetscFunctionBegin; 6563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6564 PetscValidType(mat, 1); 6565 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6566 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6567 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6568 MatCheckPreallocated(mat, 1); 6569 6570 PetscCall(ISGetLocalSize(is, &numRows)); 6571 PetscCall(ISGetIndices(is, &rows)); 6572 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6573 PetscCall(ISRestoreIndices(is, &rows)); 6574 PetscFunctionReturn(PETSC_SUCCESS); 6575 } 6576 6577 /*@ 6578 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6579 of a set of rows and columns of a matrix; using local numbering of rows. 6580 6581 Collective 6582 6583 Input Parameters: 6584 + mat - the matrix 6585 . numRows - the number of rows to remove 6586 . rows - the global row indices 6587 . diag - value put in all diagonals of eliminated rows 6588 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6589 - b - optional vector of right hand side, that will be adjusted by provided solution 6590 6591 Level: intermediate 6592 6593 Notes: 6594 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6595 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6596 6597 See `MatZeroRowsColumns()` for details on how this routine operates. 6598 6599 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6600 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6601 @*/ 6602 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6603 { 6604 IS is, newis; 6605 const PetscInt *newRows; 6606 6607 PetscFunctionBegin; 6608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6609 PetscValidType(mat, 1); 6610 if (numRows) PetscAssertPointer(rows, 3); 6611 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6612 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6613 MatCheckPreallocated(mat, 1); 6614 6615 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6616 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6617 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6618 PetscCall(ISGetIndices(newis, &newRows)); 6619 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6620 PetscCall(ISRestoreIndices(newis, &newRows)); 6621 PetscCall(ISDestroy(&newis)); 6622 PetscCall(ISDestroy(&is)); 6623 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6624 PetscFunctionReturn(PETSC_SUCCESS); 6625 } 6626 6627 /*@ 6628 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6629 of a set of rows and columns of a matrix; using local numbering of rows. 6630 6631 Collective 6632 6633 Input Parameters: 6634 + mat - the matrix 6635 . is - index set of rows to remove 6636 . diag - value put in all diagonals of eliminated rows 6637 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6638 - b - optional vector of right hand side, that will be adjusted by provided solution 6639 6640 Level: intermediate 6641 6642 Notes: 6643 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6644 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6645 6646 See `MatZeroRowsColumns()` for details on how this routine operates. 6647 6648 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6649 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6650 @*/ 6651 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6652 { 6653 PetscInt numRows; 6654 const PetscInt *rows; 6655 6656 PetscFunctionBegin; 6657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6658 PetscValidType(mat, 1); 6659 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6660 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6661 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6662 MatCheckPreallocated(mat, 1); 6663 6664 PetscCall(ISGetLocalSize(is, &numRows)); 6665 PetscCall(ISGetIndices(is, &rows)); 6666 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6667 PetscCall(ISRestoreIndices(is, &rows)); 6668 PetscFunctionReturn(PETSC_SUCCESS); 6669 } 6670 6671 /*@C 6672 MatGetSize - Returns the numbers of rows and columns in a matrix. 6673 6674 Not Collective 6675 6676 Input Parameter: 6677 . mat - the matrix 6678 6679 Output Parameters: 6680 + m - the number of global rows 6681 - n - the number of global columns 6682 6683 Level: beginner 6684 6685 Note: 6686 Both output parameters can be `NULL` on input. 6687 6688 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6689 @*/ 6690 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6691 { 6692 PetscFunctionBegin; 6693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6694 if (m) *m = mat->rmap->N; 6695 if (n) *n = mat->cmap->N; 6696 PetscFunctionReturn(PETSC_SUCCESS); 6697 } 6698 6699 /*@C 6700 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6701 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6702 6703 Not Collective 6704 6705 Input Parameter: 6706 . mat - the matrix 6707 6708 Output Parameters: 6709 + m - the number of local rows, use `NULL` to not obtain this value 6710 - n - the number of local columns, use `NULL` to not obtain this value 6711 6712 Level: beginner 6713 6714 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6715 @*/ 6716 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6717 { 6718 PetscFunctionBegin; 6719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6720 if (m) PetscAssertPointer(m, 2); 6721 if (n) PetscAssertPointer(n, 3); 6722 if (m) *m = mat->rmap->n; 6723 if (n) *n = mat->cmap->n; 6724 PetscFunctionReturn(PETSC_SUCCESS); 6725 } 6726 6727 /*@C 6728 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6729 vector one multiplies this matrix by that are owned by this processor. 6730 6731 Not Collective, unless matrix has not been allocated, then collective 6732 6733 Input Parameter: 6734 . mat - the matrix 6735 6736 Output Parameters: 6737 + m - the global index of the first local column, use `NULL` to not obtain this value 6738 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6739 6740 Level: developer 6741 6742 Note: 6743 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6744 Layouts](sec_matlayout) for details on matrix layouts. 6745 6746 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6747 @*/ 6748 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6749 { 6750 PetscFunctionBegin; 6751 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6752 PetscValidType(mat, 1); 6753 if (m) PetscAssertPointer(m, 2); 6754 if (n) PetscAssertPointer(n, 3); 6755 MatCheckPreallocated(mat, 1); 6756 if (m) *m = mat->cmap->rstart; 6757 if (n) *n = mat->cmap->rend; 6758 PetscFunctionReturn(PETSC_SUCCESS); 6759 } 6760 6761 /*@C 6762 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6763 this MPI process. 6764 6765 Not Collective 6766 6767 Input Parameter: 6768 . mat - the matrix 6769 6770 Output Parameters: 6771 + m - the global index of the first local row, use `NULL` to not obtain this value 6772 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6773 6774 Level: beginner 6775 6776 Note: 6777 For all matrices it returns the range of matrix rows associated with rows of a vector that 6778 would contain the result of a matrix vector product with this matrix. See [Matrix 6779 Layouts](sec_matlayout) for details on matrix layouts. 6780 6781 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6782 `PetscLayout` 6783 @*/ 6784 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6785 { 6786 PetscFunctionBegin; 6787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6788 PetscValidType(mat, 1); 6789 if (m) PetscAssertPointer(m, 2); 6790 if (n) PetscAssertPointer(n, 3); 6791 MatCheckPreallocated(mat, 1); 6792 if (m) *m = mat->rmap->rstart; 6793 if (n) *n = mat->rmap->rend; 6794 PetscFunctionReturn(PETSC_SUCCESS); 6795 } 6796 6797 /*@C 6798 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6799 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6800 6801 Not Collective, unless matrix has not been allocated 6802 6803 Input Parameter: 6804 . mat - the matrix 6805 6806 Output Parameter: 6807 . ranges - start of each processors portion plus one more than the total length at the end 6808 6809 Level: beginner 6810 6811 Note: 6812 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6813 would contain the result of a matrix vector product with this matrix. See [Matrix 6814 Layouts](sec_matlayout) for details on matrix layouts. 6815 6816 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6817 @*/ 6818 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6819 { 6820 PetscFunctionBegin; 6821 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6822 PetscValidType(mat, 1); 6823 MatCheckPreallocated(mat, 1); 6824 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6825 PetscFunctionReturn(PETSC_SUCCESS); 6826 } 6827 6828 /*@C 6829 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6830 vector one multiplies this vector by that are owned by each processor. 6831 6832 Not Collective, unless matrix has not been allocated 6833 6834 Input Parameter: 6835 . mat - the matrix 6836 6837 Output Parameter: 6838 . ranges - start of each processors portion plus one more than the total length at the end 6839 6840 Level: beginner 6841 6842 Note: 6843 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6844 Layouts](sec_matlayout) for details on matrix layouts. 6845 6846 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6847 @*/ 6848 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6849 { 6850 PetscFunctionBegin; 6851 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6852 PetscValidType(mat, 1); 6853 MatCheckPreallocated(mat, 1); 6854 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6855 PetscFunctionReturn(PETSC_SUCCESS); 6856 } 6857 6858 /*@C 6859 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6860 6861 Not Collective 6862 6863 Input Parameter: 6864 . A - matrix 6865 6866 Output Parameters: 6867 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6868 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6869 6870 Level: intermediate 6871 6872 Note: 6873 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6874 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6875 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6876 details on matrix layouts. 6877 6878 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6879 @*/ 6880 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6881 { 6882 PetscErrorCode (*f)(Mat, IS *, IS *); 6883 6884 PetscFunctionBegin; 6885 MatCheckPreallocated(A, 1); 6886 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6887 if (f) { 6888 PetscCall((*f)(A, rows, cols)); 6889 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6890 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6891 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6892 } 6893 PetscFunctionReturn(PETSC_SUCCESS); 6894 } 6895 6896 /*@C 6897 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6898 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6899 to complete the factorization. 6900 6901 Collective 6902 6903 Input Parameters: 6904 + fact - the factorized matrix obtained with `MatGetFactor()` 6905 . mat - the matrix 6906 . row - row permutation 6907 . col - column permutation 6908 - info - structure containing 6909 .vb 6910 levels - number of levels of fill. 6911 expected fill - as ratio of original fill. 6912 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6913 missing diagonal entries) 6914 .ve 6915 6916 Level: developer 6917 6918 Notes: 6919 See [Matrix Factorization](sec_matfactor) for additional information. 6920 6921 Most users should employ the `KSP` interface for linear solvers 6922 instead of working directly with matrix algebra routines such as this. 6923 See, e.g., `KSPCreate()`. 6924 6925 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 6926 6927 Developer Note: 6928 The Fortran interface is not autogenerated as the 6929 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6930 6931 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6932 `MatGetOrdering()`, `MatFactorInfo` 6933 @*/ 6934 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6935 { 6936 PetscFunctionBegin; 6937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6938 PetscValidType(mat, 2); 6939 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6940 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6941 PetscAssertPointer(info, 5); 6942 PetscAssertPointer(fact, 1); 6943 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6944 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6945 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6946 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6947 MatCheckPreallocated(mat, 2); 6948 6949 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6950 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6951 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6952 PetscFunctionReturn(PETSC_SUCCESS); 6953 } 6954 6955 /*@C 6956 MatICCFactorSymbolic - Performs symbolic incomplete 6957 Cholesky factorization for a symmetric matrix. Use 6958 `MatCholeskyFactorNumeric()` to complete the factorization. 6959 6960 Collective 6961 6962 Input Parameters: 6963 + fact - the factorized matrix obtained with `MatGetFactor()` 6964 . mat - the matrix to be factored 6965 . perm - row and column permutation 6966 - info - structure containing 6967 .vb 6968 levels - number of levels of fill. 6969 expected fill - as ratio of original fill. 6970 .ve 6971 6972 Level: developer 6973 6974 Notes: 6975 Most users should employ the `KSP` interface for linear solvers 6976 instead of working directly with matrix algebra routines such as this. 6977 See, e.g., `KSPCreate()`. 6978 6979 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 6980 6981 Developer Note: 6982 The Fortran interface is not autogenerated as the 6983 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6984 6985 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6986 @*/ 6987 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6988 { 6989 PetscFunctionBegin; 6990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6991 PetscValidType(mat, 2); 6992 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6993 PetscAssertPointer(info, 4); 6994 PetscAssertPointer(fact, 1); 6995 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6996 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6997 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6998 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6999 MatCheckPreallocated(mat, 2); 7000 7001 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7002 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7003 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7004 PetscFunctionReturn(PETSC_SUCCESS); 7005 } 7006 7007 /*@C 7008 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7009 points to an array of valid matrices, they may be reused to store the new 7010 submatrices. 7011 7012 Collective 7013 7014 Input Parameters: 7015 + mat - the matrix 7016 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7017 . irow - index set of rows to extract 7018 . icol - index set of columns to extract 7019 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7020 7021 Output Parameter: 7022 . submat - the array of submatrices 7023 7024 Level: advanced 7025 7026 Notes: 7027 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7028 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7029 to extract a parallel submatrix. 7030 7031 Some matrix types place restrictions on the row and column 7032 indices, such as that they be sorted or that they be equal to each other. 7033 7034 The index sets may not have duplicate entries. 7035 7036 When extracting submatrices from a parallel matrix, each processor can 7037 form a different submatrix by setting the rows and columns of its 7038 individual index sets according to the local submatrix desired. 7039 7040 When finished using the submatrices, the user should destroy 7041 them with `MatDestroySubMatrices()`. 7042 7043 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7044 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7045 7046 This routine creates the matrices in submat; you should NOT create them before 7047 calling it. It also allocates the array of matrix pointers submat. 7048 7049 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7050 request one row/column in a block, they must request all rows/columns that are in 7051 that block. For example, if the block size is 2 you cannot request just row 0 and 7052 column 0. 7053 7054 Fortran Note: 7055 The Fortran interface is slightly different from that given below; it 7056 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7057 7058 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7059 @*/ 7060 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7061 { 7062 PetscInt i; 7063 PetscBool eq; 7064 7065 PetscFunctionBegin; 7066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7067 PetscValidType(mat, 1); 7068 if (n) { 7069 PetscAssertPointer(irow, 3); 7070 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7071 PetscAssertPointer(icol, 4); 7072 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7073 } 7074 PetscAssertPointer(submat, 6); 7075 if (n && scall == MAT_REUSE_MATRIX) { 7076 PetscAssertPointer(*submat, 6); 7077 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7078 } 7079 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7080 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7081 MatCheckPreallocated(mat, 1); 7082 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7083 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7084 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7085 for (i = 0; i < n; i++) { 7086 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7087 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7088 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7089 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7090 if (mat->boundtocpu && mat->bindingpropagates) { 7091 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7092 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7093 } 7094 #endif 7095 } 7096 PetscFunctionReturn(PETSC_SUCCESS); 7097 } 7098 7099 /*@C 7100 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7101 7102 Collective 7103 7104 Input Parameters: 7105 + mat - the matrix 7106 . n - the number of submatrixes to be extracted 7107 . irow - index set of rows to extract 7108 . icol - index set of columns to extract 7109 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7110 7111 Output Parameter: 7112 . submat - the array of submatrices 7113 7114 Level: advanced 7115 7116 Note: 7117 This is used by `PCGASM` 7118 7119 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7120 @*/ 7121 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7122 { 7123 PetscInt i; 7124 PetscBool eq; 7125 7126 PetscFunctionBegin; 7127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7128 PetscValidType(mat, 1); 7129 if (n) { 7130 PetscAssertPointer(irow, 3); 7131 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7132 PetscAssertPointer(icol, 4); 7133 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7134 } 7135 PetscAssertPointer(submat, 6); 7136 if (n && scall == MAT_REUSE_MATRIX) { 7137 PetscAssertPointer(*submat, 6); 7138 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7139 } 7140 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7141 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7142 MatCheckPreallocated(mat, 1); 7143 7144 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7145 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7146 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7147 for (i = 0; i < n; i++) { 7148 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7149 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7150 } 7151 PetscFunctionReturn(PETSC_SUCCESS); 7152 } 7153 7154 /*@C 7155 MatDestroyMatrices - Destroys an array of matrices. 7156 7157 Collective 7158 7159 Input Parameters: 7160 + n - the number of local matrices 7161 - mat - the matrices (this is a pointer to the array of matrices) 7162 7163 Level: advanced 7164 7165 Note: 7166 Frees not only the matrices, but also the array that contains the matrices 7167 7168 Fortran Note: 7169 This does not free the array. 7170 7171 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7172 @*/ 7173 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7174 { 7175 PetscInt i; 7176 7177 PetscFunctionBegin; 7178 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7179 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7180 PetscAssertPointer(mat, 2); 7181 7182 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7183 7184 /* memory is allocated even if n = 0 */ 7185 PetscCall(PetscFree(*mat)); 7186 PetscFunctionReturn(PETSC_SUCCESS); 7187 } 7188 7189 /*@C 7190 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7191 7192 Collective 7193 7194 Input Parameters: 7195 + n - the number of local matrices 7196 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7197 sequence of `MatCreateSubMatrices()`) 7198 7199 Level: advanced 7200 7201 Note: 7202 Frees not only the matrices, but also the array that contains the matrices 7203 7204 Fortran Note: 7205 This does not free the array. 7206 7207 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7208 @*/ 7209 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7210 { 7211 Mat mat0; 7212 7213 PetscFunctionBegin; 7214 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7215 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7216 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7217 PetscAssertPointer(mat, 2); 7218 7219 mat0 = (*mat)[0]; 7220 if (mat0 && mat0->ops->destroysubmatrices) { 7221 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7222 } else { 7223 PetscCall(MatDestroyMatrices(n, mat)); 7224 } 7225 PetscFunctionReturn(PETSC_SUCCESS); 7226 } 7227 7228 /*@C 7229 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7230 7231 Collective 7232 7233 Input Parameter: 7234 . mat - the matrix 7235 7236 Output Parameter: 7237 . matstruct - the sequential matrix with the nonzero structure of mat 7238 7239 Level: developer 7240 7241 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7242 @*/ 7243 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7244 { 7245 PetscFunctionBegin; 7246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7247 PetscAssertPointer(matstruct, 2); 7248 7249 PetscValidType(mat, 1); 7250 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7251 MatCheckPreallocated(mat, 1); 7252 7253 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7254 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7255 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7256 PetscFunctionReturn(PETSC_SUCCESS); 7257 } 7258 7259 /*@C 7260 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7261 7262 Collective 7263 7264 Input Parameter: 7265 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7266 sequence of `MatGetSeqNonzeroStructure()`) 7267 7268 Level: advanced 7269 7270 Note: 7271 Frees not only the matrices, but also the array that contains the matrices 7272 7273 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7274 @*/ 7275 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7276 { 7277 PetscFunctionBegin; 7278 PetscAssertPointer(mat, 1); 7279 PetscCall(MatDestroy(mat)); 7280 PetscFunctionReturn(PETSC_SUCCESS); 7281 } 7282 7283 /*@ 7284 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7285 replaces the index sets by larger ones that represent submatrices with 7286 additional overlap. 7287 7288 Collective 7289 7290 Input Parameters: 7291 + mat - the matrix 7292 . n - the number of index sets 7293 . is - the array of index sets (these index sets will changed during the call) 7294 - ov - the additional overlap requested 7295 7296 Options Database Key: 7297 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7298 7299 Level: developer 7300 7301 Note: 7302 The computed overlap preserves the matrix block sizes when the blocks are square. 7303 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7304 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7305 7306 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7307 @*/ 7308 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7309 { 7310 PetscInt i, bs, cbs; 7311 7312 PetscFunctionBegin; 7313 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7314 PetscValidType(mat, 1); 7315 PetscValidLogicalCollectiveInt(mat, n, 2); 7316 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7317 if (n) { 7318 PetscAssertPointer(is, 3); 7319 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7320 } 7321 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7322 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7323 MatCheckPreallocated(mat, 1); 7324 7325 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7326 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7327 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7328 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7329 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7330 if (bs == cbs) { 7331 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7332 } 7333 PetscFunctionReturn(PETSC_SUCCESS); 7334 } 7335 7336 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7337 7338 /*@ 7339 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7340 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7341 additional overlap. 7342 7343 Collective 7344 7345 Input Parameters: 7346 + mat - the matrix 7347 . n - the number of index sets 7348 . is - the array of index sets (these index sets will changed during the call) 7349 - ov - the additional overlap requested 7350 7351 ` Options Database Key: 7352 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7353 7354 Level: developer 7355 7356 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7357 @*/ 7358 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7359 { 7360 PetscInt i; 7361 7362 PetscFunctionBegin; 7363 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7364 PetscValidType(mat, 1); 7365 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7366 if (n) { 7367 PetscAssertPointer(is, 3); 7368 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7369 } 7370 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7371 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7372 MatCheckPreallocated(mat, 1); 7373 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7374 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7375 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7376 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7377 PetscFunctionReturn(PETSC_SUCCESS); 7378 } 7379 7380 /*@ 7381 MatGetBlockSize - Returns the matrix block size. 7382 7383 Not Collective 7384 7385 Input Parameter: 7386 . mat - the matrix 7387 7388 Output Parameter: 7389 . bs - block size 7390 7391 Level: intermediate 7392 7393 Notes: 7394 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7395 7396 If the block size has not been set yet this routine returns 1. 7397 7398 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7399 @*/ 7400 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7401 { 7402 PetscFunctionBegin; 7403 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7404 PetscAssertPointer(bs, 2); 7405 *bs = PetscAbs(mat->rmap->bs); 7406 PetscFunctionReturn(PETSC_SUCCESS); 7407 } 7408 7409 /*@ 7410 MatGetBlockSizes - Returns the matrix block row and column sizes. 7411 7412 Not Collective 7413 7414 Input Parameter: 7415 . mat - the matrix 7416 7417 Output Parameters: 7418 + rbs - row block size 7419 - cbs - column block size 7420 7421 Level: intermediate 7422 7423 Notes: 7424 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7425 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7426 7427 If a block size has not been set yet this routine returns 1. 7428 7429 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7430 @*/ 7431 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7432 { 7433 PetscFunctionBegin; 7434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7435 if (rbs) PetscAssertPointer(rbs, 2); 7436 if (cbs) PetscAssertPointer(cbs, 3); 7437 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7438 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7439 PetscFunctionReturn(PETSC_SUCCESS); 7440 } 7441 7442 /*@ 7443 MatSetBlockSize - Sets the matrix block size. 7444 7445 Logically Collective 7446 7447 Input Parameters: 7448 + mat - the matrix 7449 - bs - block size 7450 7451 Level: intermediate 7452 7453 Notes: 7454 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7455 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7456 7457 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7458 is compatible with the matrix local sizes. 7459 7460 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7461 @*/ 7462 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7463 { 7464 PetscFunctionBegin; 7465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7466 PetscValidLogicalCollectiveInt(mat, bs, 2); 7467 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7468 PetscFunctionReturn(PETSC_SUCCESS); 7469 } 7470 7471 typedef struct { 7472 PetscInt n; 7473 IS *is; 7474 Mat *mat; 7475 PetscObjectState nonzerostate; 7476 Mat C; 7477 } EnvelopeData; 7478 7479 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7480 { 7481 EnvelopeData *edata = (EnvelopeData *)ptr; 7482 7483 PetscFunctionBegin; 7484 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7485 PetscCall(PetscFree(edata->is)); 7486 PetscCall(PetscFree(edata)); 7487 PetscFunctionReturn(PETSC_SUCCESS); 7488 } 7489 7490 /*@ 7491 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7492 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7493 7494 Collective 7495 7496 Input Parameter: 7497 . mat - the matrix 7498 7499 Level: intermediate 7500 7501 Notes: 7502 There can be zeros within the blocks 7503 7504 The blocks can overlap between processes, including laying on more than two processes 7505 7506 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7507 @*/ 7508 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7509 { 7510 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7511 PetscInt *diag, *odiag, sc; 7512 VecScatter scatter; 7513 PetscScalar *seqv; 7514 const PetscScalar *parv; 7515 const PetscInt *ia, *ja; 7516 PetscBool set, flag, done; 7517 Mat AA = mat, A; 7518 MPI_Comm comm; 7519 PetscMPIInt rank, size, tag; 7520 MPI_Status status; 7521 PetscContainer container; 7522 EnvelopeData *edata; 7523 Vec seq, par; 7524 IS isglobal; 7525 7526 PetscFunctionBegin; 7527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7528 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7529 if (!set || !flag) { 7530 /* TODO: only needs nonzero structure of transpose */ 7531 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7532 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7533 } 7534 PetscCall(MatAIJGetLocalMat(AA, &A)); 7535 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7536 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7537 7538 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7539 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7540 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7541 PetscCallMPI(MPI_Comm_size(comm, &size)); 7542 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7543 7544 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7545 7546 if (rank > 0) { 7547 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7548 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7549 } 7550 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7551 for (i = 0; i < n; i++) { 7552 env = PetscMax(env, ja[ia[i + 1] - 1]); 7553 II = rstart + i; 7554 if (env == II) { 7555 starts[lblocks] = tbs; 7556 sizes[lblocks++] = 1 + II - tbs; 7557 tbs = 1 + II; 7558 } 7559 } 7560 if (rank < size - 1) { 7561 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7562 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7563 } 7564 7565 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7566 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7567 PetscCall(MatDestroy(&A)); 7568 7569 PetscCall(PetscNew(&edata)); 7570 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7571 edata->n = lblocks; 7572 /* create IS needed for extracting blocks from the original matrix */ 7573 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7574 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7575 7576 /* Create the resulting inverse matrix structure with preallocation information */ 7577 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7578 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7579 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7580 PetscCall(MatSetType(edata->C, MATAIJ)); 7581 7582 /* Communicate the start and end of each row, from each block to the correct rank */ 7583 /* TODO: Use PetscSF instead of VecScatter */ 7584 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7585 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7586 PetscCall(VecGetArrayWrite(seq, &seqv)); 7587 for (PetscInt i = 0; i < lblocks; i++) { 7588 for (PetscInt j = 0; j < sizes[i]; j++) { 7589 seqv[cnt] = starts[i]; 7590 seqv[cnt + 1] = starts[i] + sizes[i]; 7591 cnt += 2; 7592 } 7593 } 7594 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7595 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7596 sc -= cnt; 7597 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7598 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7599 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7600 PetscCall(ISDestroy(&isglobal)); 7601 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7602 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7603 PetscCall(VecScatterDestroy(&scatter)); 7604 PetscCall(VecDestroy(&seq)); 7605 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7606 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7607 PetscCall(VecGetArrayRead(par, &parv)); 7608 cnt = 0; 7609 PetscCall(MatGetSize(mat, NULL, &n)); 7610 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7611 PetscInt start, end, d = 0, od = 0; 7612 7613 start = (PetscInt)PetscRealPart(parv[cnt]); 7614 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7615 cnt += 2; 7616 7617 if (start < cstart) { 7618 od += cstart - start + n - cend; 7619 d += cend - cstart; 7620 } else if (start < cend) { 7621 od += n - cend; 7622 d += cend - start; 7623 } else od += n - start; 7624 if (end <= cstart) { 7625 od -= cstart - end + n - cend; 7626 d -= cend - cstart; 7627 } else if (end < cend) { 7628 od -= n - cend; 7629 d -= cend - end; 7630 } else od -= n - end; 7631 7632 odiag[i] = od; 7633 diag[i] = d; 7634 } 7635 PetscCall(VecRestoreArrayRead(par, &parv)); 7636 PetscCall(VecDestroy(&par)); 7637 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7638 PetscCall(PetscFree2(diag, odiag)); 7639 PetscCall(PetscFree2(sizes, starts)); 7640 7641 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7642 PetscCall(PetscContainerSetPointer(container, edata)); 7643 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7644 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7645 PetscCall(PetscObjectDereference((PetscObject)container)); 7646 PetscFunctionReturn(PETSC_SUCCESS); 7647 } 7648 7649 /*@ 7650 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7651 7652 Collective 7653 7654 Input Parameters: 7655 + A - the matrix 7656 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7657 7658 Output Parameter: 7659 . C - matrix with inverted block diagonal of `A` 7660 7661 Level: advanced 7662 7663 Note: 7664 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7665 7666 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7667 @*/ 7668 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7669 { 7670 PetscContainer container; 7671 EnvelopeData *edata; 7672 PetscObjectState nonzerostate; 7673 7674 PetscFunctionBegin; 7675 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7676 if (!container) { 7677 PetscCall(MatComputeVariableBlockEnvelope(A)); 7678 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7679 } 7680 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7681 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7682 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7683 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7684 7685 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7686 *C = edata->C; 7687 7688 for (PetscInt i = 0; i < edata->n; i++) { 7689 Mat D; 7690 PetscScalar *dvalues; 7691 7692 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7693 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7694 PetscCall(MatSeqDenseInvert(D)); 7695 PetscCall(MatDenseGetArray(D, &dvalues)); 7696 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7697 PetscCall(MatDestroy(&D)); 7698 } 7699 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7700 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7701 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7702 PetscFunctionReturn(PETSC_SUCCESS); 7703 } 7704 7705 /*@ 7706 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7707 7708 Logically Collective 7709 7710 Input Parameters: 7711 + mat - the matrix 7712 . nblocks - the number of blocks on this process, each block can only exist on a single process 7713 - bsizes - the block sizes 7714 7715 Level: intermediate 7716 7717 Notes: 7718 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7719 7720 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. 7721 7722 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7723 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7724 @*/ 7725 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7726 { 7727 PetscInt i, ncnt = 0, nlocal; 7728 7729 PetscFunctionBegin; 7730 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7731 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7732 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7733 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7734 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); 7735 PetscCall(PetscFree(mat->bsizes)); 7736 mat->nblocks = nblocks; 7737 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7738 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7739 PetscFunctionReturn(PETSC_SUCCESS); 7740 } 7741 7742 /*@C 7743 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7744 7745 Logically Collective; No Fortran Support 7746 7747 Input Parameter: 7748 . mat - the matrix 7749 7750 Output Parameters: 7751 + nblocks - the number of blocks on this process 7752 - bsizes - the block sizes 7753 7754 Level: intermediate 7755 7756 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7757 @*/ 7758 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7759 { 7760 PetscFunctionBegin; 7761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7762 *nblocks = mat->nblocks; 7763 *bsizes = mat->bsizes; 7764 PetscFunctionReturn(PETSC_SUCCESS); 7765 } 7766 7767 /*@ 7768 MatSetBlockSizes - Sets the matrix block row and column sizes. 7769 7770 Logically Collective 7771 7772 Input Parameters: 7773 + mat - the matrix 7774 . rbs - row block size 7775 - cbs - column block size 7776 7777 Level: intermediate 7778 7779 Notes: 7780 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7781 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7782 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7783 7784 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7785 are compatible with the matrix local sizes. 7786 7787 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7788 7789 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7790 @*/ 7791 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7792 { 7793 PetscFunctionBegin; 7794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7795 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7796 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7797 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7798 if (mat->rmap->refcnt) { 7799 ISLocalToGlobalMapping l2g = NULL; 7800 PetscLayout nmap = NULL; 7801 7802 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7803 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7804 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7805 mat->rmap = nmap; 7806 mat->rmap->mapping = l2g; 7807 } 7808 if (mat->cmap->refcnt) { 7809 ISLocalToGlobalMapping l2g = NULL; 7810 PetscLayout nmap = NULL; 7811 7812 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7813 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7814 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7815 mat->cmap = nmap; 7816 mat->cmap->mapping = l2g; 7817 } 7818 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7819 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7820 PetscFunctionReturn(PETSC_SUCCESS); 7821 } 7822 7823 /*@ 7824 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7825 7826 Logically Collective 7827 7828 Input Parameters: 7829 + mat - the matrix 7830 . fromRow - matrix from which to copy row block size 7831 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7832 7833 Level: developer 7834 7835 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7836 @*/ 7837 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7838 { 7839 PetscFunctionBegin; 7840 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7841 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7842 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7843 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7844 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7845 PetscFunctionReturn(PETSC_SUCCESS); 7846 } 7847 7848 /*@ 7849 MatResidual - Default routine to calculate the residual r = b - Ax 7850 7851 Collective 7852 7853 Input Parameters: 7854 + mat - the matrix 7855 . b - the right-hand-side 7856 - x - the approximate solution 7857 7858 Output Parameter: 7859 . r - location to store the residual 7860 7861 Level: developer 7862 7863 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7864 @*/ 7865 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7866 { 7867 PetscFunctionBegin; 7868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7869 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7870 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7871 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7872 PetscValidType(mat, 1); 7873 MatCheckPreallocated(mat, 1); 7874 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7875 if (!mat->ops->residual) { 7876 PetscCall(MatMult(mat, x, r)); 7877 PetscCall(VecAYPX(r, -1.0, b)); 7878 } else { 7879 PetscUseTypeMethod(mat, residual, b, x, r); 7880 } 7881 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7882 PetscFunctionReturn(PETSC_SUCCESS); 7883 } 7884 7885 /*MC 7886 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7887 7888 Synopsis: 7889 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7890 7891 Not Collective 7892 7893 Input Parameters: 7894 + A - the matrix 7895 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7896 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7897 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7898 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7899 always used. 7900 7901 Output Parameters: 7902 + n - number of local rows in the (possibly compressed) matrix 7903 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7904 . ja - the column indices 7905 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7906 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7907 7908 Level: developer 7909 7910 Note: 7911 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7912 7913 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7914 M*/ 7915 7916 /*MC 7917 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7918 7919 Synopsis: 7920 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7921 7922 Not Collective 7923 7924 Input Parameters: 7925 + A - the matrix 7926 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7927 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7928 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7929 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7930 always used. 7931 . n - number of local rows in the (possibly compressed) matrix 7932 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7933 . ja - the column indices 7934 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7935 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7936 7937 Level: developer 7938 7939 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7940 M*/ 7941 7942 /*@C 7943 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7944 7945 Collective 7946 7947 Input Parameters: 7948 + mat - the matrix 7949 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7950 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7951 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7952 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7953 always used. 7954 7955 Output Parameters: 7956 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7957 . 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 7958 . ja - the column indices, use `NULL` if not needed 7959 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7960 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7961 7962 Level: developer 7963 7964 Notes: 7965 You CANNOT change any of the ia[] or ja[] values. 7966 7967 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7968 7969 Fortran Notes: 7970 Use 7971 .vb 7972 PetscInt, pointer :: ia(:),ja(:) 7973 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7974 ! Access the ith and jth entries via ia(i) and ja(j) 7975 .ve 7976 7977 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7978 7979 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7980 @*/ 7981 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7982 { 7983 PetscFunctionBegin; 7984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7985 PetscValidType(mat, 1); 7986 if (n) PetscAssertPointer(n, 5); 7987 if (ia) PetscAssertPointer(ia, 6); 7988 if (ja) PetscAssertPointer(ja, 7); 7989 if (done) PetscAssertPointer(done, 8); 7990 MatCheckPreallocated(mat, 1); 7991 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7992 else { 7993 if (done) *done = PETSC_TRUE; 7994 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7995 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7996 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7997 } 7998 PetscFunctionReturn(PETSC_SUCCESS); 7999 } 8000 8001 /*@C 8002 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8003 8004 Collective 8005 8006 Input Parameters: 8007 + mat - the matrix 8008 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8009 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8010 symmetrized 8011 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8012 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8013 always used. 8014 . n - number of columns in the (possibly compressed) matrix 8015 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8016 - ja - the row indices 8017 8018 Output Parameter: 8019 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8020 8021 Level: developer 8022 8023 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8024 @*/ 8025 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8026 { 8027 PetscFunctionBegin; 8028 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8029 PetscValidType(mat, 1); 8030 PetscAssertPointer(n, 5); 8031 if (ia) PetscAssertPointer(ia, 6); 8032 if (ja) PetscAssertPointer(ja, 7); 8033 PetscAssertPointer(done, 8); 8034 MatCheckPreallocated(mat, 1); 8035 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8036 else { 8037 *done = PETSC_TRUE; 8038 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8039 } 8040 PetscFunctionReturn(PETSC_SUCCESS); 8041 } 8042 8043 /*@C 8044 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8045 8046 Collective 8047 8048 Input Parameters: 8049 + mat - the matrix 8050 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8051 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8052 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8053 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8054 always used. 8055 . n - size of (possibly compressed) matrix 8056 . ia - the row pointers 8057 - ja - the column indices 8058 8059 Output Parameter: 8060 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8061 8062 Level: developer 8063 8064 Note: 8065 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8066 us of the array after it has been restored. If you pass `NULL`, it will 8067 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8068 8069 Fortran Note: 8070 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8071 8072 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8073 @*/ 8074 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8075 { 8076 PetscFunctionBegin; 8077 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8078 PetscValidType(mat, 1); 8079 if (ia) PetscAssertPointer(ia, 6); 8080 if (ja) PetscAssertPointer(ja, 7); 8081 if (done) PetscAssertPointer(done, 8); 8082 MatCheckPreallocated(mat, 1); 8083 8084 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8085 else { 8086 if (done) *done = PETSC_TRUE; 8087 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8088 if (n) *n = 0; 8089 if (ia) *ia = NULL; 8090 if (ja) *ja = NULL; 8091 } 8092 PetscFunctionReturn(PETSC_SUCCESS); 8093 } 8094 8095 /*@C 8096 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8097 8098 Collective 8099 8100 Input Parameters: 8101 + mat - the matrix 8102 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8103 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8104 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8105 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8106 always used. 8107 8108 Output Parameters: 8109 + n - size of (possibly compressed) matrix 8110 . ia - the column pointers 8111 . ja - the row indices 8112 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8113 8114 Level: developer 8115 8116 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8117 @*/ 8118 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8119 { 8120 PetscFunctionBegin; 8121 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8122 PetscValidType(mat, 1); 8123 if (ia) PetscAssertPointer(ia, 6); 8124 if (ja) PetscAssertPointer(ja, 7); 8125 PetscAssertPointer(done, 8); 8126 MatCheckPreallocated(mat, 1); 8127 8128 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8129 else { 8130 *done = PETSC_TRUE; 8131 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8132 if (n) *n = 0; 8133 if (ia) *ia = NULL; 8134 if (ja) *ja = NULL; 8135 } 8136 PetscFunctionReturn(PETSC_SUCCESS); 8137 } 8138 8139 /*@C 8140 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8141 `MatGetColumnIJ()`. 8142 8143 Collective 8144 8145 Input Parameters: 8146 + mat - the matrix 8147 . ncolors - maximum color value 8148 . n - number of entries in colorarray 8149 - colorarray - array indicating color for each column 8150 8151 Output Parameter: 8152 . iscoloring - coloring generated using colorarray information 8153 8154 Level: developer 8155 8156 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8157 @*/ 8158 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8159 { 8160 PetscFunctionBegin; 8161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8162 PetscValidType(mat, 1); 8163 PetscAssertPointer(colorarray, 4); 8164 PetscAssertPointer(iscoloring, 5); 8165 MatCheckPreallocated(mat, 1); 8166 8167 if (!mat->ops->coloringpatch) { 8168 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8169 } else { 8170 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8171 } 8172 PetscFunctionReturn(PETSC_SUCCESS); 8173 } 8174 8175 /*@ 8176 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8177 8178 Logically Collective 8179 8180 Input Parameter: 8181 . mat - the factored matrix to be reset 8182 8183 Level: developer 8184 8185 Notes: 8186 This routine should be used only with factored matrices formed by in-place 8187 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8188 format). This option can save memory, for example, when solving nonlinear 8189 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8190 ILU(0) preconditioner. 8191 8192 One can specify in-place ILU(0) factorization by calling 8193 .vb 8194 PCType(pc,PCILU); 8195 PCFactorSeUseInPlace(pc); 8196 .ve 8197 or by using the options -pc_type ilu -pc_factor_in_place 8198 8199 In-place factorization ILU(0) can also be used as a local 8200 solver for the blocks within the block Jacobi or additive Schwarz 8201 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8202 for details on setting local solver options. 8203 8204 Most users should employ the `KSP` interface for linear solvers 8205 instead of working directly with matrix algebra routines such as this. 8206 See, e.g., `KSPCreate()`. 8207 8208 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8209 @*/ 8210 PetscErrorCode MatSetUnfactored(Mat mat) 8211 { 8212 PetscFunctionBegin; 8213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8214 PetscValidType(mat, 1); 8215 MatCheckPreallocated(mat, 1); 8216 mat->factortype = MAT_FACTOR_NONE; 8217 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8218 PetscUseTypeMethod(mat, setunfactored); 8219 PetscFunctionReturn(PETSC_SUCCESS); 8220 } 8221 8222 /*MC 8223 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8224 8225 Synopsis: 8226 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8227 8228 Not Collective 8229 8230 Input Parameter: 8231 . x - matrix 8232 8233 Output Parameters: 8234 + xx_v - the Fortran pointer to the array 8235 - ierr - error code 8236 8237 Example of Usage: 8238 .vb 8239 PetscScalar, pointer xx_v(:,:) 8240 .... 8241 call MatDenseGetArrayF90(x,xx_v,ierr) 8242 a = xx_v(3) 8243 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8244 .ve 8245 8246 Level: advanced 8247 8248 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8249 M*/ 8250 8251 /*MC 8252 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8253 accessed with `MatDenseGetArrayF90()`. 8254 8255 Synopsis: 8256 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8257 8258 Not Collective 8259 8260 Input Parameters: 8261 + x - matrix 8262 - xx_v - the Fortran90 pointer to the array 8263 8264 Output Parameter: 8265 . ierr - error code 8266 8267 Example of Usage: 8268 .vb 8269 PetscScalar, pointer xx_v(:,:) 8270 .... 8271 call MatDenseGetArrayF90(x,xx_v,ierr) 8272 a = xx_v(3) 8273 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8274 .ve 8275 8276 Level: advanced 8277 8278 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8279 M*/ 8280 8281 /*MC 8282 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8283 8284 Synopsis: 8285 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8286 8287 Not Collective 8288 8289 Input Parameter: 8290 . x - matrix 8291 8292 Output Parameters: 8293 + xx_v - the Fortran pointer to the array 8294 - ierr - error code 8295 8296 Example of Usage: 8297 .vb 8298 PetscScalar, pointer xx_v(:) 8299 .... 8300 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8301 a = xx_v(3) 8302 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8303 .ve 8304 8305 Level: advanced 8306 8307 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8308 M*/ 8309 8310 /*MC 8311 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8312 accessed with `MatSeqAIJGetArrayF90()`. 8313 8314 Synopsis: 8315 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8316 8317 Not Collective 8318 8319 Input Parameters: 8320 + x - matrix 8321 - xx_v - the Fortran90 pointer to the array 8322 8323 Output Parameter: 8324 . ierr - error code 8325 8326 Example of Usage: 8327 .vb 8328 PetscScalar, pointer xx_v(:) 8329 .... 8330 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8331 a = xx_v(3) 8332 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8333 .ve 8334 8335 Level: advanced 8336 8337 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8338 M*/ 8339 8340 /*@ 8341 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8342 as the original matrix. 8343 8344 Collective 8345 8346 Input Parameters: 8347 + mat - the original matrix 8348 . isrow - parallel `IS` containing the rows this processor should obtain 8349 . 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. 8350 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8351 8352 Output Parameter: 8353 . newmat - the new submatrix, of the same type as the original matrix 8354 8355 Level: advanced 8356 8357 Notes: 8358 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8359 8360 Some matrix types place restrictions on the row and column indices, such 8361 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; 8362 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8363 8364 The index sets may not have duplicate entries. 8365 8366 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8367 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8368 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8369 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8370 you are finished using it. 8371 8372 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8373 the input matrix. 8374 8375 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8376 8377 If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature 8378 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8379 8380 Example usage: 8381 Consider the following 8x8 matrix with 34 non-zero values, that is 8382 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8383 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8384 as follows 8385 .vb 8386 1 2 0 | 0 3 0 | 0 4 8387 Proc0 0 5 6 | 7 0 0 | 8 0 8388 9 0 10 | 11 0 0 | 12 0 8389 ------------------------------------- 8390 13 0 14 | 15 16 17 | 0 0 8391 Proc1 0 18 0 | 19 20 21 | 0 0 8392 0 0 0 | 22 23 0 | 24 0 8393 ------------------------------------- 8394 Proc2 25 26 27 | 0 0 28 | 29 0 8395 30 0 0 | 31 32 33 | 0 34 8396 .ve 8397 8398 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8399 8400 .vb 8401 2 0 | 0 3 0 | 0 8402 Proc0 5 6 | 7 0 0 | 8 8403 ------------------------------- 8404 Proc1 18 0 | 19 20 21 | 0 8405 ------------------------------- 8406 Proc2 26 27 | 0 0 28 | 29 8407 0 0 | 31 32 33 | 0 8408 .ve 8409 8410 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8411 @*/ 8412 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8413 { 8414 PetscMPIInt size; 8415 Mat *local; 8416 IS iscoltmp; 8417 PetscBool flg; 8418 8419 PetscFunctionBegin; 8420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8421 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8422 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8423 PetscAssertPointer(newmat, 5); 8424 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8425 PetscValidType(mat, 1); 8426 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8427 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8428 8429 MatCheckPreallocated(mat, 1); 8430 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8431 8432 if (!iscol || isrow == iscol) { 8433 PetscBool stride; 8434 PetscMPIInt grabentirematrix = 0, grab; 8435 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8436 if (stride) { 8437 PetscInt first, step, n, rstart, rend; 8438 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8439 if (step == 1) { 8440 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8441 if (rstart == first) { 8442 PetscCall(ISGetLocalSize(isrow, &n)); 8443 if (n == rend - rstart) grabentirematrix = 1; 8444 } 8445 } 8446 } 8447 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8448 if (grab) { 8449 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8450 if (cll == MAT_INITIAL_MATRIX) { 8451 *newmat = mat; 8452 PetscCall(PetscObjectReference((PetscObject)mat)); 8453 } 8454 PetscFunctionReturn(PETSC_SUCCESS); 8455 } 8456 } 8457 8458 if (!iscol) { 8459 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8460 } else { 8461 iscoltmp = iscol; 8462 } 8463 8464 /* if original matrix is on just one processor then use submatrix generated */ 8465 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8466 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8467 goto setproperties; 8468 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8469 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8470 *newmat = *local; 8471 PetscCall(PetscFree(local)); 8472 goto setproperties; 8473 } else if (!mat->ops->createsubmatrix) { 8474 /* Create a new matrix type that implements the operation using the full matrix */ 8475 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8476 switch (cll) { 8477 case MAT_INITIAL_MATRIX: 8478 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8479 break; 8480 case MAT_REUSE_MATRIX: 8481 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8482 break; 8483 default: 8484 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8485 } 8486 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8487 goto setproperties; 8488 } 8489 8490 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8491 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8492 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8493 8494 setproperties: 8495 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8496 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8497 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8498 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8499 PetscFunctionReturn(PETSC_SUCCESS); 8500 } 8501 8502 /*@ 8503 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8504 8505 Not Collective 8506 8507 Input Parameters: 8508 + A - the matrix we wish to propagate options from 8509 - B - the matrix we wish to propagate options to 8510 8511 Level: beginner 8512 8513 Note: 8514 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8515 8516 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8517 @*/ 8518 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8519 { 8520 PetscFunctionBegin; 8521 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8522 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8523 B->symmetry_eternal = A->symmetry_eternal; 8524 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8525 B->symmetric = A->symmetric; 8526 B->structurally_symmetric = A->structurally_symmetric; 8527 B->spd = A->spd; 8528 B->hermitian = A->hermitian; 8529 PetscFunctionReturn(PETSC_SUCCESS); 8530 } 8531 8532 /*@ 8533 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8534 used during the assembly process to store values that belong to 8535 other processors. 8536 8537 Not Collective 8538 8539 Input Parameters: 8540 + mat - the matrix 8541 . size - the initial size of the stash. 8542 - bsize - the initial size of the block-stash(if used). 8543 8544 Options Database Keys: 8545 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8546 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8547 8548 Level: intermediate 8549 8550 Notes: 8551 The block-stash is used for values set with `MatSetValuesBlocked()` while 8552 the stash is used for values set with `MatSetValues()` 8553 8554 Run with the option -info and look for output of the form 8555 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8556 to determine the appropriate value, MM, to use for size and 8557 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8558 to determine the value, BMM to use for bsize 8559 8560 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8561 @*/ 8562 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8563 { 8564 PetscFunctionBegin; 8565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8566 PetscValidType(mat, 1); 8567 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8568 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8569 PetscFunctionReturn(PETSC_SUCCESS); 8570 } 8571 8572 /*@ 8573 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8574 the matrix 8575 8576 Neighbor-wise Collective 8577 8578 Input Parameters: 8579 + A - the matrix 8580 . x - the vector to be multiplied by the interpolation operator 8581 - y - the vector to be added to the result 8582 8583 Output Parameter: 8584 . w - the resulting vector 8585 8586 Level: intermediate 8587 8588 Notes: 8589 `w` may be the same vector as `y`. 8590 8591 This allows one to use either the restriction or interpolation (its transpose) 8592 matrix to do the interpolation 8593 8594 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8595 @*/ 8596 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8597 { 8598 PetscInt M, N, Ny; 8599 8600 PetscFunctionBegin; 8601 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8602 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8603 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8604 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8605 PetscCall(MatGetSize(A, &M, &N)); 8606 PetscCall(VecGetSize(y, &Ny)); 8607 if (M == Ny) { 8608 PetscCall(MatMultAdd(A, x, y, w)); 8609 } else { 8610 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8611 } 8612 PetscFunctionReturn(PETSC_SUCCESS); 8613 } 8614 8615 /*@ 8616 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8617 the matrix 8618 8619 Neighbor-wise Collective 8620 8621 Input Parameters: 8622 + A - the matrix 8623 - x - the vector to be interpolated 8624 8625 Output Parameter: 8626 . y - the resulting vector 8627 8628 Level: intermediate 8629 8630 Note: 8631 This allows one to use either the restriction or interpolation (its transpose) 8632 matrix to do the interpolation 8633 8634 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8635 @*/ 8636 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8637 { 8638 PetscInt M, N, Ny; 8639 8640 PetscFunctionBegin; 8641 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8642 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8643 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8644 PetscCall(MatGetSize(A, &M, &N)); 8645 PetscCall(VecGetSize(y, &Ny)); 8646 if (M == Ny) { 8647 PetscCall(MatMult(A, x, y)); 8648 } else { 8649 PetscCall(MatMultTranspose(A, x, y)); 8650 } 8651 PetscFunctionReturn(PETSC_SUCCESS); 8652 } 8653 8654 /*@ 8655 MatRestrict - $y = A*x$ or $A^T*x$ 8656 8657 Neighbor-wise Collective 8658 8659 Input Parameters: 8660 + A - the matrix 8661 - x - the vector to be restricted 8662 8663 Output Parameter: 8664 . y - the resulting vector 8665 8666 Level: intermediate 8667 8668 Note: 8669 This allows one to use either the restriction or interpolation (its transpose) 8670 matrix to do the restriction 8671 8672 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8673 @*/ 8674 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8675 { 8676 PetscInt M, N, Ny; 8677 8678 PetscFunctionBegin; 8679 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8680 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8681 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8682 PetscCall(MatGetSize(A, &M, &N)); 8683 PetscCall(VecGetSize(y, &Ny)); 8684 if (M == Ny) { 8685 PetscCall(MatMult(A, x, y)); 8686 } else { 8687 PetscCall(MatMultTranspose(A, x, y)); 8688 } 8689 PetscFunctionReturn(PETSC_SUCCESS); 8690 } 8691 8692 /*@ 8693 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8694 8695 Neighbor-wise Collective 8696 8697 Input Parameters: 8698 + A - the matrix 8699 . x - the input dense matrix to be multiplied 8700 - w - the input dense matrix to be added to the result 8701 8702 Output Parameter: 8703 . y - the output dense matrix 8704 8705 Level: intermediate 8706 8707 Note: 8708 This allows one to use either the restriction or interpolation (its transpose) 8709 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8710 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8711 8712 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8713 @*/ 8714 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8715 { 8716 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8717 PetscBool trans = PETSC_TRUE; 8718 MatReuse reuse = MAT_INITIAL_MATRIX; 8719 8720 PetscFunctionBegin; 8721 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8722 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8723 PetscValidType(x, 2); 8724 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8725 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8726 PetscCall(MatGetSize(A, &M, &N)); 8727 PetscCall(MatGetSize(x, &Mx, &Nx)); 8728 if (N == Mx) trans = PETSC_FALSE; 8729 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); 8730 Mo = trans ? N : M; 8731 if (*y) { 8732 PetscCall(MatGetSize(*y, &My, &Ny)); 8733 if (Mo == My && Nx == Ny) { 8734 reuse = MAT_REUSE_MATRIX; 8735 } else { 8736 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); 8737 PetscCall(MatDestroy(y)); 8738 } 8739 } 8740 8741 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8742 PetscBool flg; 8743 8744 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8745 if (w) { 8746 PetscInt My, Ny, Mw, Nw; 8747 8748 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8749 PetscCall(MatGetSize(*y, &My, &Ny)); 8750 PetscCall(MatGetSize(w, &Mw, &Nw)); 8751 if (!flg || My != Mw || Ny != Nw) w = NULL; 8752 } 8753 if (!w) { 8754 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8755 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8756 PetscCall(PetscObjectDereference((PetscObject)w)); 8757 } else { 8758 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8759 } 8760 } 8761 if (!trans) { 8762 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8763 } else { 8764 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8765 } 8766 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8767 PetscFunctionReturn(PETSC_SUCCESS); 8768 } 8769 8770 /*@ 8771 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8772 8773 Neighbor-wise Collective 8774 8775 Input Parameters: 8776 + A - the matrix 8777 - x - the input dense matrix 8778 8779 Output Parameter: 8780 . y - the output dense matrix 8781 8782 Level: intermediate 8783 8784 Note: 8785 This allows one to use either the restriction or interpolation (its transpose) 8786 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8787 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8788 8789 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8790 @*/ 8791 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8792 { 8793 PetscFunctionBegin; 8794 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8795 PetscFunctionReturn(PETSC_SUCCESS); 8796 } 8797 8798 /*@ 8799 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8800 8801 Neighbor-wise Collective 8802 8803 Input Parameters: 8804 + A - the matrix 8805 - x - the input dense matrix 8806 8807 Output Parameter: 8808 . y - the output dense matrix 8809 8810 Level: intermediate 8811 8812 Note: 8813 This allows one to use either the restriction or interpolation (its transpose) 8814 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8815 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8816 8817 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8818 @*/ 8819 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8820 { 8821 PetscFunctionBegin; 8822 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8823 PetscFunctionReturn(PETSC_SUCCESS); 8824 } 8825 8826 /*@ 8827 MatGetNullSpace - retrieves the null space of a matrix. 8828 8829 Logically Collective 8830 8831 Input Parameters: 8832 + mat - the matrix 8833 - nullsp - the null space object 8834 8835 Level: developer 8836 8837 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8838 @*/ 8839 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8840 { 8841 PetscFunctionBegin; 8842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8843 PetscAssertPointer(nullsp, 2); 8844 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8845 PetscFunctionReturn(PETSC_SUCCESS); 8846 } 8847 8848 /*@ 8849 MatSetNullSpace - attaches a null space to a matrix. 8850 8851 Logically Collective 8852 8853 Input Parameters: 8854 + mat - the matrix 8855 - nullsp - the null space object 8856 8857 Level: advanced 8858 8859 Notes: 8860 This null space is used by the `KSP` linear solvers to solve singular systems. 8861 8862 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` 8863 8864 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 8865 to zero but the linear system will still be solved in a least squares sense. 8866 8867 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8868 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)$. 8869 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 8870 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 8871 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$). 8872 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8873 8874 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8875 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8876 routine also automatically calls `MatSetTransposeNullSpace()`. 8877 8878 The user should call `MatNullSpaceDestroy()`. 8879 8880 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8881 `KSPSetPCSide()` 8882 @*/ 8883 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8884 { 8885 PetscFunctionBegin; 8886 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8887 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8888 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8889 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8890 mat->nullsp = nullsp; 8891 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8892 PetscFunctionReturn(PETSC_SUCCESS); 8893 } 8894 8895 /*@ 8896 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8897 8898 Logically Collective 8899 8900 Input Parameters: 8901 + mat - the matrix 8902 - nullsp - the null space object 8903 8904 Level: developer 8905 8906 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8907 @*/ 8908 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8909 { 8910 PetscFunctionBegin; 8911 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8912 PetscValidType(mat, 1); 8913 PetscAssertPointer(nullsp, 2); 8914 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8915 PetscFunctionReturn(PETSC_SUCCESS); 8916 } 8917 8918 /*@ 8919 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8920 8921 Logically Collective 8922 8923 Input Parameters: 8924 + mat - the matrix 8925 - nullsp - the null space object 8926 8927 Level: advanced 8928 8929 Notes: 8930 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8931 8932 See `MatSetNullSpace()` 8933 8934 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8935 @*/ 8936 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8937 { 8938 PetscFunctionBegin; 8939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8940 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8941 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8942 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8943 mat->transnullsp = nullsp; 8944 PetscFunctionReturn(PETSC_SUCCESS); 8945 } 8946 8947 /*@ 8948 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8949 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8950 8951 Logically Collective 8952 8953 Input Parameters: 8954 + mat - the matrix 8955 - nullsp - the null space object 8956 8957 Level: advanced 8958 8959 Notes: 8960 Overwrites any previous near null space that may have been attached 8961 8962 You can remove the null space by calling this routine with an `nullsp` of `NULL` 8963 8964 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8965 @*/ 8966 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8967 { 8968 PetscFunctionBegin; 8969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8970 PetscValidType(mat, 1); 8971 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8972 MatCheckPreallocated(mat, 1); 8973 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8974 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8975 mat->nearnullsp = nullsp; 8976 PetscFunctionReturn(PETSC_SUCCESS); 8977 } 8978 8979 /*@ 8980 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8981 8982 Not Collective 8983 8984 Input Parameter: 8985 . mat - the matrix 8986 8987 Output Parameter: 8988 . nullsp - the null space object, `NULL` if not set 8989 8990 Level: advanced 8991 8992 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8993 @*/ 8994 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8995 { 8996 PetscFunctionBegin; 8997 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8998 PetscValidType(mat, 1); 8999 PetscAssertPointer(nullsp, 2); 9000 MatCheckPreallocated(mat, 1); 9001 *nullsp = mat->nearnullsp; 9002 PetscFunctionReturn(PETSC_SUCCESS); 9003 } 9004 9005 /*@C 9006 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9007 9008 Collective 9009 9010 Input Parameters: 9011 + mat - the matrix 9012 . row - row/column permutation 9013 - info - information on desired factorization process 9014 9015 Level: developer 9016 9017 Notes: 9018 Probably really in-place only when level of fill is zero, otherwise allocates 9019 new space to store factored matrix and deletes previous memory. 9020 9021 Most users should employ the `KSP` interface for linear solvers 9022 instead of working directly with matrix algebra routines such as this. 9023 See, e.g., `KSPCreate()`. 9024 9025 Developer Note: 9026 The Fortran interface is not autogenerated as the 9027 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9028 9029 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9030 @*/ 9031 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9032 { 9033 PetscFunctionBegin; 9034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9035 PetscValidType(mat, 1); 9036 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9037 PetscAssertPointer(info, 3); 9038 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9040 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9041 MatCheckPreallocated(mat, 1); 9042 PetscUseTypeMethod(mat, iccfactor, row, info); 9043 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9044 PetscFunctionReturn(PETSC_SUCCESS); 9045 } 9046 9047 /*@ 9048 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9049 ghosted ones. 9050 9051 Not Collective 9052 9053 Input Parameters: 9054 + mat - the matrix 9055 - diag - the diagonal values, including ghost ones 9056 9057 Level: developer 9058 9059 Notes: 9060 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9061 9062 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9063 9064 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9065 @*/ 9066 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9067 { 9068 PetscMPIInt size; 9069 9070 PetscFunctionBegin; 9071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9072 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9073 PetscValidType(mat, 1); 9074 9075 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9076 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9077 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9078 if (size == 1) { 9079 PetscInt n, m; 9080 PetscCall(VecGetSize(diag, &n)); 9081 PetscCall(MatGetSize(mat, NULL, &m)); 9082 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9083 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9084 } else { 9085 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9086 } 9087 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9088 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9089 PetscFunctionReturn(PETSC_SUCCESS); 9090 } 9091 9092 /*@ 9093 MatGetInertia - Gets the inertia from a factored matrix 9094 9095 Collective 9096 9097 Input Parameter: 9098 . mat - the matrix 9099 9100 Output Parameters: 9101 + nneg - number of negative eigenvalues 9102 . nzero - number of zero eigenvalues 9103 - npos - number of positive eigenvalues 9104 9105 Level: advanced 9106 9107 Note: 9108 Matrix must have been factored by `MatCholeskyFactor()` 9109 9110 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9111 @*/ 9112 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9113 { 9114 PetscFunctionBegin; 9115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9116 PetscValidType(mat, 1); 9117 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9118 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9119 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9120 PetscFunctionReturn(PETSC_SUCCESS); 9121 } 9122 9123 /*@C 9124 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9125 9126 Neighbor-wise Collective 9127 9128 Input Parameters: 9129 + mat - the factored matrix obtained with `MatGetFactor()` 9130 - b - the right-hand-side vectors 9131 9132 Output Parameter: 9133 . x - the result vectors 9134 9135 Level: developer 9136 9137 Note: 9138 The vectors `b` and `x` cannot be the same. I.e., one cannot 9139 call `MatSolves`(A,x,x). 9140 9141 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9142 @*/ 9143 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9144 { 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9147 PetscValidType(mat, 1); 9148 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9149 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9150 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9151 9152 MatCheckPreallocated(mat, 1); 9153 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9154 PetscUseTypeMethod(mat, solves, b, x); 9155 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9156 PetscFunctionReturn(PETSC_SUCCESS); 9157 } 9158 9159 /*@ 9160 MatIsSymmetric - Test whether a matrix is symmetric 9161 9162 Collective 9163 9164 Input Parameters: 9165 + A - the matrix to test 9166 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9167 9168 Output Parameter: 9169 . flg - the result 9170 9171 Level: intermediate 9172 9173 Notes: 9174 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9175 9176 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9177 9178 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9179 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9180 9181 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9182 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9183 @*/ 9184 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9185 { 9186 PetscFunctionBegin; 9187 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9188 PetscAssertPointer(flg, 3); 9189 9190 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9191 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9192 else { 9193 PetscUseTypeMethod(A, issymmetric, tol, flg); 9194 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9195 } 9196 PetscFunctionReturn(PETSC_SUCCESS); 9197 } 9198 9199 /*@ 9200 MatIsHermitian - Test whether a matrix is Hermitian 9201 9202 Collective 9203 9204 Input Parameters: 9205 + A - the matrix to test 9206 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9207 9208 Output Parameter: 9209 . flg - the result 9210 9211 Level: intermediate 9212 9213 Notes: 9214 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9215 9216 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9217 9218 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9219 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9220 9221 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9222 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9223 @*/ 9224 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9225 { 9226 PetscFunctionBegin; 9227 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9228 PetscAssertPointer(flg, 3); 9229 9230 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9231 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9232 else { 9233 PetscUseTypeMethod(A, ishermitian, tol, flg); 9234 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9235 } 9236 PetscFunctionReturn(PETSC_SUCCESS); 9237 } 9238 9239 /*@ 9240 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9241 9242 Not Collective 9243 9244 Input Parameter: 9245 . A - the matrix to check 9246 9247 Output Parameters: 9248 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9249 - flg - the result (only valid if set is `PETSC_TRUE`) 9250 9251 Level: advanced 9252 9253 Notes: 9254 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9255 if you want it explicitly checked 9256 9257 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9258 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9259 9260 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9261 @*/ 9262 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9263 { 9264 PetscFunctionBegin; 9265 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9266 PetscAssertPointer(set, 2); 9267 PetscAssertPointer(flg, 3); 9268 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9269 *set = PETSC_TRUE; 9270 *flg = PetscBool3ToBool(A->symmetric); 9271 } else { 9272 *set = PETSC_FALSE; 9273 } 9274 PetscFunctionReturn(PETSC_SUCCESS); 9275 } 9276 9277 /*@ 9278 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9279 9280 Not Collective 9281 9282 Input Parameter: 9283 . A - the matrix to check 9284 9285 Output Parameters: 9286 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9287 - flg - the result (only valid if set is `PETSC_TRUE`) 9288 9289 Level: advanced 9290 9291 Notes: 9292 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9293 9294 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9295 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9296 9297 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9298 @*/ 9299 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9300 { 9301 PetscFunctionBegin; 9302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9303 PetscAssertPointer(set, 2); 9304 PetscAssertPointer(flg, 3); 9305 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9306 *set = PETSC_TRUE; 9307 *flg = PetscBool3ToBool(A->spd); 9308 } else { 9309 *set = PETSC_FALSE; 9310 } 9311 PetscFunctionReturn(PETSC_SUCCESS); 9312 } 9313 9314 /*@ 9315 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9316 9317 Not Collective 9318 9319 Input Parameter: 9320 . A - the matrix to check 9321 9322 Output Parameters: 9323 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9324 - flg - the result (only valid if set is `PETSC_TRUE`) 9325 9326 Level: advanced 9327 9328 Notes: 9329 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9330 if you want it explicitly checked 9331 9332 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9333 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9334 9335 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9336 @*/ 9337 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9338 { 9339 PetscFunctionBegin; 9340 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9341 PetscAssertPointer(set, 2); 9342 PetscAssertPointer(flg, 3); 9343 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9344 *set = PETSC_TRUE; 9345 *flg = PetscBool3ToBool(A->hermitian); 9346 } else { 9347 *set = PETSC_FALSE; 9348 } 9349 PetscFunctionReturn(PETSC_SUCCESS); 9350 } 9351 9352 /*@ 9353 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9354 9355 Collective 9356 9357 Input Parameter: 9358 . A - the matrix to test 9359 9360 Output Parameter: 9361 . flg - the result 9362 9363 Level: intermediate 9364 9365 Notes: 9366 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9367 9368 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 9369 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9370 9371 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9372 @*/ 9373 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9374 { 9375 PetscFunctionBegin; 9376 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9377 PetscAssertPointer(flg, 2); 9378 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9379 *flg = PetscBool3ToBool(A->structurally_symmetric); 9380 } else { 9381 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9382 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9383 } 9384 PetscFunctionReturn(PETSC_SUCCESS); 9385 } 9386 9387 /*@ 9388 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9389 9390 Not Collective 9391 9392 Input Parameter: 9393 . A - the matrix to check 9394 9395 Output Parameters: 9396 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9397 - flg - the result (only valid if set is PETSC_TRUE) 9398 9399 Level: advanced 9400 9401 Notes: 9402 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 9403 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9404 9405 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9406 9407 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9408 @*/ 9409 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9410 { 9411 PetscFunctionBegin; 9412 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9413 PetscAssertPointer(set, 2); 9414 PetscAssertPointer(flg, 3); 9415 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9416 *set = PETSC_TRUE; 9417 *flg = PetscBool3ToBool(A->structurally_symmetric); 9418 } else { 9419 *set = PETSC_FALSE; 9420 } 9421 PetscFunctionReturn(PETSC_SUCCESS); 9422 } 9423 9424 /*@ 9425 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9426 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9427 9428 Not Collective 9429 9430 Input Parameter: 9431 . mat - the matrix 9432 9433 Output Parameters: 9434 + nstash - the size of the stash 9435 . reallocs - the number of additional mallocs incurred. 9436 . bnstash - the size of the block stash 9437 - breallocs - the number of additional mallocs incurred.in the block stash 9438 9439 Level: advanced 9440 9441 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9442 @*/ 9443 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9444 { 9445 PetscFunctionBegin; 9446 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9447 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9448 PetscFunctionReturn(PETSC_SUCCESS); 9449 } 9450 9451 /*@C 9452 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9453 parallel layout, `PetscLayout` for rows and columns 9454 9455 Collective 9456 9457 Input Parameter: 9458 . mat - the matrix 9459 9460 Output Parameters: 9461 + right - (optional) vector that the matrix can be multiplied against 9462 - left - (optional) vector that the matrix vector product can be stored in 9463 9464 Level: advanced 9465 9466 Notes: 9467 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()`. 9468 9469 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9470 9471 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9472 @*/ 9473 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9474 { 9475 PetscFunctionBegin; 9476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9477 PetscValidType(mat, 1); 9478 if (mat->ops->getvecs) { 9479 PetscUseTypeMethod(mat, getvecs, right, left); 9480 } else { 9481 if (right) { 9482 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9483 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9484 PetscCall(VecSetType(*right, mat->defaultvectype)); 9485 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9486 if (mat->boundtocpu && mat->bindingpropagates) { 9487 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9488 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9489 } 9490 #endif 9491 } 9492 if (left) { 9493 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9494 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9495 PetscCall(VecSetType(*left, mat->defaultvectype)); 9496 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9497 if (mat->boundtocpu && mat->bindingpropagates) { 9498 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9499 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9500 } 9501 #endif 9502 } 9503 } 9504 PetscFunctionReturn(PETSC_SUCCESS); 9505 } 9506 9507 /*@C 9508 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9509 with default values. 9510 9511 Not Collective 9512 9513 Input Parameter: 9514 . info - the `MatFactorInfo` data structure 9515 9516 Level: developer 9517 9518 Notes: 9519 The solvers are generally used through the `KSP` and `PC` objects, for example 9520 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9521 9522 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9523 9524 Developer Note: 9525 The Fortran interface is not autogenerated as the 9526 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9527 9528 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9529 @*/ 9530 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9531 { 9532 PetscFunctionBegin; 9533 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9534 PetscFunctionReturn(PETSC_SUCCESS); 9535 } 9536 9537 /*@ 9538 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9539 9540 Collective 9541 9542 Input Parameters: 9543 + mat - the factored matrix 9544 - is - the index set defining the Schur indices (0-based) 9545 9546 Level: advanced 9547 9548 Notes: 9549 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9550 9551 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9552 9553 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9554 9555 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9556 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9557 @*/ 9558 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9559 { 9560 PetscErrorCode (*f)(Mat, IS); 9561 9562 PetscFunctionBegin; 9563 PetscValidType(mat, 1); 9564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9565 PetscValidType(is, 2); 9566 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9567 PetscCheckSameComm(mat, 1, is, 2); 9568 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9569 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9570 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9571 PetscCall(MatDestroy(&mat->schur)); 9572 PetscCall((*f)(mat, is)); 9573 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9574 PetscFunctionReturn(PETSC_SUCCESS); 9575 } 9576 9577 /*@ 9578 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9579 9580 Logically Collective 9581 9582 Input Parameters: 9583 + F - the factored matrix obtained by calling `MatGetFactor()` 9584 . S - location where to return the Schur complement, can be `NULL` 9585 - status - the status of the Schur complement matrix, can be `NULL` 9586 9587 Level: advanced 9588 9589 Notes: 9590 You must call `MatFactorSetSchurIS()` before calling this routine. 9591 9592 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9593 9594 The routine provides a copy of the Schur matrix stored within the solver data structures. 9595 The caller must destroy the object when it is no longer needed. 9596 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9597 9598 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) 9599 9600 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9601 9602 Developer Note: 9603 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9604 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9605 9606 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9607 @*/ 9608 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9609 { 9610 PetscFunctionBegin; 9611 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9612 if (S) PetscAssertPointer(S, 2); 9613 if (status) PetscAssertPointer(status, 3); 9614 if (S) { 9615 PetscErrorCode (*f)(Mat, Mat *); 9616 9617 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9618 if (f) { 9619 PetscCall((*f)(F, S)); 9620 } else { 9621 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9622 } 9623 } 9624 if (status) *status = F->schur_status; 9625 PetscFunctionReturn(PETSC_SUCCESS); 9626 } 9627 9628 /*@ 9629 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9630 9631 Logically Collective 9632 9633 Input Parameters: 9634 + F - the factored matrix obtained by calling `MatGetFactor()` 9635 . S - location where to return the Schur complement, can be `NULL` 9636 - status - the status of the Schur complement matrix, can be `NULL` 9637 9638 Level: advanced 9639 9640 Notes: 9641 You must call `MatFactorSetSchurIS()` before calling this routine. 9642 9643 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9644 9645 The routine returns a the Schur Complement stored within the data structures of the solver. 9646 9647 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9648 9649 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9650 9651 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9652 9653 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9654 9655 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9656 @*/ 9657 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9658 { 9659 PetscFunctionBegin; 9660 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9661 if (S) { 9662 PetscAssertPointer(S, 2); 9663 *S = F->schur; 9664 } 9665 if (status) { 9666 PetscAssertPointer(status, 3); 9667 *status = F->schur_status; 9668 } 9669 PetscFunctionReturn(PETSC_SUCCESS); 9670 } 9671 9672 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9673 { 9674 Mat S = F->schur; 9675 9676 PetscFunctionBegin; 9677 switch (F->schur_status) { 9678 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9679 case MAT_FACTOR_SCHUR_INVERTED: 9680 if (S) { 9681 S->ops->solve = NULL; 9682 S->ops->matsolve = NULL; 9683 S->ops->solvetranspose = NULL; 9684 S->ops->matsolvetranspose = NULL; 9685 S->ops->solveadd = NULL; 9686 S->ops->solvetransposeadd = NULL; 9687 S->factortype = MAT_FACTOR_NONE; 9688 PetscCall(PetscFree(S->solvertype)); 9689 } 9690 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9691 break; 9692 default: 9693 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9694 } 9695 PetscFunctionReturn(PETSC_SUCCESS); 9696 } 9697 9698 /*@ 9699 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9700 9701 Logically Collective 9702 9703 Input Parameters: 9704 + F - the factored matrix obtained by calling `MatGetFactor()` 9705 . S - location where the Schur complement is stored 9706 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9707 9708 Level: advanced 9709 9710 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9711 @*/ 9712 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9713 { 9714 PetscFunctionBegin; 9715 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9716 if (S) { 9717 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9718 *S = NULL; 9719 } 9720 F->schur_status = status; 9721 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9722 PetscFunctionReturn(PETSC_SUCCESS); 9723 } 9724 9725 /*@ 9726 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9727 9728 Logically Collective 9729 9730 Input Parameters: 9731 + F - the factored matrix obtained by calling `MatGetFactor()` 9732 . rhs - location where the right hand side of the Schur complement system is stored 9733 - sol - location where the solution of the Schur complement system has to be returned 9734 9735 Level: advanced 9736 9737 Notes: 9738 The sizes of the vectors should match the size of the Schur complement 9739 9740 Must be called after `MatFactorSetSchurIS()` 9741 9742 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9743 @*/ 9744 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9745 { 9746 PetscFunctionBegin; 9747 PetscValidType(F, 1); 9748 PetscValidType(rhs, 2); 9749 PetscValidType(sol, 3); 9750 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9751 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9752 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9753 PetscCheckSameComm(F, 1, rhs, 2); 9754 PetscCheckSameComm(F, 1, sol, 3); 9755 PetscCall(MatFactorFactorizeSchurComplement(F)); 9756 switch (F->schur_status) { 9757 case MAT_FACTOR_SCHUR_FACTORED: 9758 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9759 break; 9760 case MAT_FACTOR_SCHUR_INVERTED: 9761 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9762 break; 9763 default: 9764 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9765 } 9766 PetscFunctionReturn(PETSC_SUCCESS); 9767 } 9768 9769 /*@ 9770 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9771 9772 Logically Collective 9773 9774 Input Parameters: 9775 + F - the factored matrix obtained by calling `MatGetFactor()` 9776 . rhs - location where the right hand side of the Schur complement system is stored 9777 - sol - location where the solution of the Schur complement system has to be returned 9778 9779 Level: advanced 9780 9781 Notes: 9782 The sizes of the vectors should match the size of the Schur complement 9783 9784 Must be called after `MatFactorSetSchurIS()` 9785 9786 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9787 @*/ 9788 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9789 { 9790 PetscFunctionBegin; 9791 PetscValidType(F, 1); 9792 PetscValidType(rhs, 2); 9793 PetscValidType(sol, 3); 9794 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9795 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9796 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9797 PetscCheckSameComm(F, 1, rhs, 2); 9798 PetscCheckSameComm(F, 1, sol, 3); 9799 PetscCall(MatFactorFactorizeSchurComplement(F)); 9800 switch (F->schur_status) { 9801 case MAT_FACTOR_SCHUR_FACTORED: 9802 PetscCall(MatSolve(F->schur, rhs, sol)); 9803 break; 9804 case MAT_FACTOR_SCHUR_INVERTED: 9805 PetscCall(MatMult(F->schur, rhs, sol)); 9806 break; 9807 default: 9808 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9809 } 9810 PetscFunctionReturn(PETSC_SUCCESS); 9811 } 9812 9813 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9814 #if PetscDefined(HAVE_CUDA) 9815 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9816 #endif 9817 9818 /* Schur status updated in the interface */ 9819 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9820 { 9821 Mat S = F->schur; 9822 9823 PetscFunctionBegin; 9824 if (S) { 9825 PetscMPIInt size; 9826 PetscBool isdense, isdensecuda; 9827 9828 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9829 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9830 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9831 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9832 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9833 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9834 if (isdense) { 9835 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9836 } else if (isdensecuda) { 9837 #if defined(PETSC_HAVE_CUDA) 9838 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9839 #endif 9840 } 9841 // HIP?????????????? 9842 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9843 } 9844 PetscFunctionReturn(PETSC_SUCCESS); 9845 } 9846 9847 /*@ 9848 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9849 9850 Logically Collective 9851 9852 Input Parameter: 9853 . F - the factored matrix obtained by calling `MatGetFactor()` 9854 9855 Level: advanced 9856 9857 Notes: 9858 Must be called after `MatFactorSetSchurIS()`. 9859 9860 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9861 9862 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9863 @*/ 9864 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9865 { 9866 PetscFunctionBegin; 9867 PetscValidType(F, 1); 9868 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9869 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9870 PetscCall(MatFactorFactorizeSchurComplement(F)); 9871 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9872 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9873 PetscFunctionReturn(PETSC_SUCCESS); 9874 } 9875 9876 /*@ 9877 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9878 9879 Logically Collective 9880 9881 Input Parameter: 9882 . F - the factored matrix obtained by calling `MatGetFactor()` 9883 9884 Level: advanced 9885 9886 Note: 9887 Must be called after `MatFactorSetSchurIS()` 9888 9889 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9890 @*/ 9891 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9892 { 9893 MatFactorInfo info; 9894 9895 PetscFunctionBegin; 9896 PetscValidType(F, 1); 9897 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9898 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9899 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9900 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9901 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9902 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9903 } else { 9904 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9905 } 9906 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9907 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9908 PetscFunctionReturn(PETSC_SUCCESS); 9909 } 9910 9911 /*@ 9912 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9913 9914 Neighbor-wise Collective 9915 9916 Input Parameters: 9917 + A - the matrix 9918 . P - the projection matrix 9919 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9920 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9921 if the result is a dense matrix this is irrelevant 9922 9923 Output Parameter: 9924 . C - the product matrix 9925 9926 Level: intermediate 9927 9928 Notes: 9929 C will be created and must be destroyed by the user with `MatDestroy()`. 9930 9931 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9932 9933 Developer Note: 9934 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9935 9936 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9937 @*/ 9938 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9939 { 9940 PetscFunctionBegin; 9941 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9942 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9943 9944 if (scall == MAT_INITIAL_MATRIX) { 9945 PetscCall(MatProductCreate(A, P, NULL, C)); 9946 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9947 PetscCall(MatProductSetAlgorithm(*C, "default")); 9948 PetscCall(MatProductSetFill(*C, fill)); 9949 9950 (*C)->product->api_user = PETSC_TRUE; 9951 PetscCall(MatProductSetFromOptions(*C)); 9952 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); 9953 PetscCall(MatProductSymbolic(*C)); 9954 } else { /* scall == MAT_REUSE_MATRIX */ 9955 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9956 } 9957 9958 PetscCall(MatProductNumeric(*C)); 9959 (*C)->symmetric = A->symmetric; 9960 (*C)->spd = A->spd; 9961 PetscFunctionReturn(PETSC_SUCCESS); 9962 } 9963 9964 /*@ 9965 MatRARt - Creates the matrix product $C = R * A * R^T$ 9966 9967 Neighbor-wise Collective 9968 9969 Input Parameters: 9970 + A - the matrix 9971 . R - the projection matrix 9972 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9973 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9974 if the result is a dense matrix this is irrelevant 9975 9976 Output Parameter: 9977 . C - the product matrix 9978 9979 Level: intermediate 9980 9981 Notes: 9982 C will be created and must be destroyed by the user with `MatDestroy()`. 9983 9984 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9985 9986 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9987 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9988 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9989 We recommend using MatPtAP(). 9990 9991 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9992 @*/ 9993 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9994 { 9995 PetscFunctionBegin; 9996 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9997 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9998 9999 if (scall == MAT_INITIAL_MATRIX) { 10000 PetscCall(MatProductCreate(A, R, NULL, C)); 10001 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10002 PetscCall(MatProductSetAlgorithm(*C, "default")); 10003 PetscCall(MatProductSetFill(*C, fill)); 10004 10005 (*C)->product->api_user = PETSC_TRUE; 10006 PetscCall(MatProductSetFromOptions(*C)); 10007 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); 10008 PetscCall(MatProductSymbolic(*C)); 10009 } else { /* scall == MAT_REUSE_MATRIX */ 10010 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10011 } 10012 10013 PetscCall(MatProductNumeric(*C)); 10014 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10015 PetscFunctionReturn(PETSC_SUCCESS); 10016 } 10017 10018 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10019 { 10020 PetscFunctionBegin; 10021 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10022 10023 if (scall == MAT_INITIAL_MATRIX) { 10024 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10025 PetscCall(MatProductCreate(A, B, NULL, C)); 10026 PetscCall(MatProductSetType(*C, ptype)); 10027 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10028 PetscCall(MatProductSetFill(*C, fill)); 10029 10030 (*C)->product->api_user = PETSC_TRUE; 10031 PetscCall(MatProductSetFromOptions(*C)); 10032 PetscCall(MatProductSymbolic(*C)); 10033 } else { /* scall == MAT_REUSE_MATRIX */ 10034 Mat_Product *product = (*C)->product; 10035 PetscBool isdense; 10036 10037 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10038 if (isdense && product && product->type != ptype) { 10039 PetscCall(MatProductClear(*C)); 10040 product = NULL; 10041 } 10042 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10043 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10044 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10045 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10046 product = (*C)->product; 10047 product->fill = fill; 10048 product->api_user = PETSC_TRUE; 10049 product->clear = PETSC_TRUE; 10050 10051 PetscCall(MatProductSetType(*C, ptype)); 10052 PetscCall(MatProductSetFromOptions(*C)); 10053 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); 10054 PetscCall(MatProductSymbolic(*C)); 10055 } else { /* user may change input matrices A or B when REUSE */ 10056 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10057 } 10058 } 10059 PetscCall(MatProductNumeric(*C)); 10060 PetscFunctionReturn(PETSC_SUCCESS); 10061 } 10062 10063 /*@ 10064 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10065 10066 Neighbor-wise Collective 10067 10068 Input Parameters: 10069 + A - the left matrix 10070 . B - the right matrix 10071 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10072 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10073 if the result is a dense matrix this is irrelevant 10074 10075 Output Parameter: 10076 . C - the product matrix 10077 10078 Notes: 10079 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10080 10081 `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 10082 call to this function with `MAT_INITIAL_MATRIX`. 10083 10084 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10085 10086 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`, 10087 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10088 10089 Example of Usage: 10090 .vb 10091 MatProductCreate(A,B,NULL,&C); 10092 MatProductSetType(C,MATPRODUCT_AB); 10093 MatProductSymbolic(C); 10094 MatProductNumeric(C); // compute C=A * B 10095 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10096 MatProductNumeric(C); 10097 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10098 MatProductNumeric(C); 10099 .ve 10100 10101 Level: intermediate 10102 10103 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10104 @*/ 10105 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10106 { 10107 PetscFunctionBegin; 10108 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10109 PetscFunctionReturn(PETSC_SUCCESS); 10110 } 10111 10112 /*@ 10113 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10114 10115 Neighbor-wise Collective 10116 10117 Input Parameters: 10118 + A - the left matrix 10119 . B - the right matrix 10120 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10121 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10122 10123 Output Parameter: 10124 . C - the product matrix 10125 10126 Options Database Key: 10127 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10128 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10129 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10130 10131 Level: intermediate 10132 10133 Notes: 10134 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10135 10136 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10137 10138 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10139 actually needed. 10140 10141 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10142 and for pairs of `MATMPIDENSE` matrices. 10143 10144 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10145 10146 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10147 @*/ 10148 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10149 { 10150 PetscFunctionBegin; 10151 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10152 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10153 PetscFunctionReturn(PETSC_SUCCESS); 10154 } 10155 10156 /*@ 10157 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10158 10159 Neighbor-wise Collective 10160 10161 Input Parameters: 10162 + A - the left matrix 10163 . B - the right matrix 10164 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10165 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10166 10167 Output Parameter: 10168 . C - the product matrix 10169 10170 Level: intermediate 10171 10172 Notes: 10173 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10174 10175 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10176 10177 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10178 10179 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10180 actually needed. 10181 10182 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10183 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10184 10185 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10186 @*/ 10187 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10188 { 10189 PetscFunctionBegin; 10190 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10191 PetscFunctionReturn(PETSC_SUCCESS); 10192 } 10193 10194 /*@ 10195 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10196 10197 Neighbor-wise Collective 10198 10199 Input Parameters: 10200 + A - the left matrix 10201 . B - the middle matrix 10202 . C - the right matrix 10203 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10204 - 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 10205 if the result is a dense matrix this is irrelevant 10206 10207 Output Parameter: 10208 . D - the product matrix 10209 10210 Level: intermediate 10211 10212 Notes: 10213 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10214 10215 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10216 10217 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10218 10219 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10220 actually needed. 10221 10222 If you have many matrices with the same non-zero structure to multiply, you 10223 should use `MAT_REUSE_MATRIX` in all calls but the first 10224 10225 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10226 @*/ 10227 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10228 { 10229 PetscFunctionBegin; 10230 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10231 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10232 10233 if (scall == MAT_INITIAL_MATRIX) { 10234 PetscCall(MatProductCreate(A, B, C, D)); 10235 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10236 PetscCall(MatProductSetAlgorithm(*D, "default")); 10237 PetscCall(MatProductSetFill(*D, fill)); 10238 10239 (*D)->product->api_user = PETSC_TRUE; 10240 PetscCall(MatProductSetFromOptions(*D)); 10241 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, 10242 ((PetscObject)C)->type_name); 10243 PetscCall(MatProductSymbolic(*D)); 10244 } else { /* user may change input matrices when REUSE */ 10245 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10246 } 10247 PetscCall(MatProductNumeric(*D)); 10248 PetscFunctionReturn(PETSC_SUCCESS); 10249 } 10250 10251 /*@ 10252 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10253 10254 Collective 10255 10256 Input Parameters: 10257 + mat - the matrix 10258 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10259 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10260 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10261 10262 Output Parameter: 10263 . matredundant - redundant matrix 10264 10265 Level: advanced 10266 10267 Notes: 10268 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10269 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10270 10271 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10272 calling it. 10273 10274 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10275 10276 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10277 @*/ 10278 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10279 { 10280 MPI_Comm comm; 10281 PetscMPIInt size; 10282 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10283 Mat_Redundant *redund = NULL; 10284 PetscSubcomm psubcomm = NULL; 10285 MPI_Comm subcomm_in = subcomm; 10286 Mat *matseq; 10287 IS isrow, iscol; 10288 PetscBool newsubcomm = PETSC_FALSE; 10289 10290 PetscFunctionBegin; 10291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10292 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10293 PetscAssertPointer(*matredundant, 5); 10294 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10295 } 10296 10297 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10298 if (size == 1 || nsubcomm == 1) { 10299 if (reuse == MAT_INITIAL_MATRIX) { 10300 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10301 } else { 10302 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"); 10303 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10304 } 10305 PetscFunctionReturn(PETSC_SUCCESS); 10306 } 10307 10308 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10309 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10310 MatCheckPreallocated(mat, 1); 10311 10312 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10313 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10314 /* create psubcomm, then get subcomm */ 10315 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10316 PetscCallMPI(MPI_Comm_size(comm, &size)); 10317 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10318 10319 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10320 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10321 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10322 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10323 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10324 newsubcomm = PETSC_TRUE; 10325 PetscCall(PetscSubcommDestroy(&psubcomm)); 10326 } 10327 10328 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10329 if (reuse == MAT_INITIAL_MATRIX) { 10330 mloc_sub = PETSC_DECIDE; 10331 nloc_sub = PETSC_DECIDE; 10332 if (bs < 1) { 10333 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10334 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10335 } else { 10336 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10337 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10338 } 10339 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10340 rstart = rend - mloc_sub; 10341 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10342 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10343 PetscCall(ISSetIdentity(iscol)); 10344 } else { /* reuse == MAT_REUSE_MATRIX */ 10345 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"); 10346 /* retrieve subcomm */ 10347 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10348 redund = (*matredundant)->redundant; 10349 isrow = redund->isrow; 10350 iscol = redund->iscol; 10351 matseq = redund->matseq; 10352 } 10353 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10354 10355 /* get matredundant over subcomm */ 10356 if (reuse == MAT_INITIAL_MATRIX) { 10357 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10358 10359 /* create a supporting struct and attach it to C for reuse */ 10360 PetscCall(PetscNew(&redund)); 10361 (*matredundant)->redundant = redund; 10362 redund->isrow = isrow; 10363 redund->iscol = iscol; 10364 redund->matseq = matseq; 10365 if (newsubcomm) { 10366 redund->subcomm = subcomm; 10367 } else { 10368 redund->subcomm = MPI_COMM_NULL; 10369 } 10370 } else { 10371 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10372 } 10373 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10374 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10375 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10376 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10377 } 10378 #endif 10379 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10380 PetscFunctionReturn(PETSC_SUCCESS); 10381 } 10382 10383 /*@C 10384 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10385 a given `Mat`. Each submatrix can span multiple procs. 10386 10387 Collective 10388 10389 Input Parameters: 10390 + mat - the matrix 10391 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10392 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10393 10394 Output Parameter: 10395 . subMat - parallel sub-matrices each spanning a given `subcomm` 10396 10397 Level: advanced 10398 10399 Notes: 10400 The submatrix partition across processors is dictated by `subComm` a 10401 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10402 is not restricted to be grouped with consecutive original MPI processes. 10403 10404 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10405 map directly to the layout of the original matrix [wrt the local 10406 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10407 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10408 the `subMat`. However the offDiagMat looses some columns - and this is 10409 reconstructed with `MatSetValues()` 10410 10411 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10412 10413 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10414 @*/ 10415 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10416 { 10417 PetscMPIInt commsize, subCommSize; 10418 10419 PetscFunctionBegin; 10420 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10421 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10422 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10423 10424 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"); 10425 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10426 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10427 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10428 PetscFunctionReturn(PETSC_SUCCESS); 10429 } 10430 10431 /*@ 10432 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10433 10434 Not Collective 10435 10436 Input Parameters: 10437 + mat - matrix to extract local submatrix from 10438 . isrow - local row indices for submatrix 10439 - iscol - local column indices for submatrix 10440 10441 Output Parameter: 10442 . submat - the submatrix 10443 10444 Level: intermediate 10445 10446 Notes: 10447 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10448 10449 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10450 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10451 10452 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10453 `MatSetValuesBlockedLocal()` will also be implemented. 10454 10455 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10456 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10457 10458 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10459 @*/ 10460 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10461 { 10462 PetscFunctionBegin; 10463 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10464 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10465 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10466 PetscCheckSameComm(isrow, 2, iscol, 3); 10467 PetscAssertPointer(submat, 4); 10468 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10469 10470 if (mat->ops->getlocalsubmatrix) { 10471 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10472 } else { 10473 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10474 } 10475 PetscFunctionReturn(PETSC_SUCCESS); 10476 } 10477 10478 /*@ 10479 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10480 10481 Not Collective 10482 10483 Input Parameters: 10484 + mat - matrix to extract local submatrix from 10485 . isrow - local row indices for submatrix 10486 . iscol - local column indices for submatrix 10487 - submat - the submatrix 10488 10489 Level: intermediate 10490 10491 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10492 @*/ 10493 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10494 { 10495 PetscFunctionBegin; 10496 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10497 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10498 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10499 PetscCheckSameComm(isrow, 2, iscol, 3); 10500 PetscAssertPointer(submat, 4); 10501 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10502 10503 if (mat->ops->restorelocalsubmatrix) { 10504 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10505 } else { 10506 PetscCall(MatDestroy(submat)); 10507 } 10508 *submat = NULL; 10509 PetscFunctionReturn(PETSC_SUCCESS); 10510 } 10511 10512 /*@ 10513 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10514 10515 Collective 10516 10517 Input Parameter: 10518 . mat - the matrix 10519 10520 Output Parameter: 10521 . is - if any rows have zero diagonals this contains the list of them 10522 10523 Level: developer 10524 10525 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10526 @*/ 10527 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10528 { 10529 PetscFunctionBegin; 10530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10531 PetscValidType(mat, 1); 10532 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10533 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10534 10535 if (!mat->ops->findzerodiagonals) { 10536 Vec diag; 10537 const PetscScalar *a; 10538 PetscInt *rows; 10539 PetscInt rStart, rEnd, r, nrow = 0; 10540 10541 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10542 PetscCall(MatGetDiagonal(mat, diag)); 10543 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10544 PetscCall(VecGetArrayRead(diag, &a)); 10545 for (r = 0; r < rEnd - rStart; ++r) 10546 if (a[r] == 0.0) ++nrow; 10547 PetscCall(PetscMalloc1(nrow, &rows)); 10548 nrow = 0; 10549 for (r = 0; r < rEnd - rStart; ++r) 10550 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10551 PetscCall(VecRestoreArrayRead(diag, &a)); 10552 PetscCall(VecDestroy(&diag)); 10553 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10554 } else { 10555 PetscUseTypeMethod(mat, findzerodiagonals, is); 10556 } 10557 PetscFunctionReturn(PETSC_SUCCESS); 10558 } 10559 10560 /*@ 10561 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10562 10563 Collective 10564 10565 Input Parameter: 10566 . mat - the matrix 10567 10568 Output Parameter: 10569 . is - contains the list of rows with off block diagonal entries 10570 10571 Level: developer 10572 10573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10574 @*/ 10575 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10576 { 10577 PetscFunctionBegin; 10578 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10579 PetscValidType(mat, 1); 10580 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10581 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10582 10583 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10584 PetscFunctionReturn(PETSC_SUCCESS); 10585 } 10586 10587 /*@C 10588 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10589 10590 Collective; No Fortran Support 10591 10592 Input Parameter: 10593 . mat - the matrix 10594 10595 Output Parameter: 10596 . values - the block inverses in column major order (FORTRAN-like) 10597 10598 Level: advanced 10599 10600 Notes: 10601 The size of the blocks is determined by the block size of the matrix. 10602 10603 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10604 10605 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10606 10607 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10608 @*/ 10609 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10610 { 10611 PetscFunctionBegin; 10612 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10613 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10614 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10615 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10616 PetscFunctionReturn(PETSC_SUCCESS); 10617 } 10618 10619 /*@C 10620 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10621 10622 Collective; No Fortran Support 10623 10624 Input Parameters: 10625 + mat - the matrix 10626 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10627 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10628 10629 Output Parameter: 10630 . values - the block inverses in column major order (FORTRAN-like) 10631 10632 Level: advanced 10633 10634 Notes: 10635 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10636 10637 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10638 10639 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10640 @*/ 10641 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10642 { 10643 PetscFunctionBegin; 10644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10645 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10646 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10647 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10648 PetscFunctionReturn(PETSC_SUCCESS); 10649 } 10650 10651 /*@ 10652 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10653 10654 Collective 10655 10656 Input Parameters: 10657 + A - the matrix 10658 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10659 10660 Level: advanced 10661 10662 Note: 10663 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10664 10665 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10666 @*/ 10667 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10668 { 10669 const PetscScalar *vals; 10670 PetscInt *dnnz; 10671 PetscInt m, rstart, rend, bs, i, j; 10672 10673 PetscFunctionBegin; 10674 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10675 PetscCall(MatGetBlockSize(A, &bs)); 10676 PetscCall(MatGetLocalSize(A, &m, NULL)); 10677 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10678 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10679 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10680 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10681 PetscCall(PetscFree(dnnz)); 10682 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10683 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10684 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10685 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10686 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10687 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10688 PetscFunctionReturn(PETSC_SUCCESS); 10689 } 10690 10691 /*@C 10692 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10693 via `MatTransposeColoringCreate()`. 10694 10695 Collective 10696 10697 Input Parameter: 10698 . c - coloring context 10699 10700 Level: intermediate 10701 10702 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10703 @*/ 10704 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10705 { 10706 MatTransposeColoring matcolor = *c; 10707 10708 PetscFunctionBegin; 10709 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10710 if (--((PetscObject)matcolor)->refct > 0) { 10711 matcolor = NULL; 10712 PetscFunctionReturn(PETSC_SUCCESS); 10713 } 10714 10715 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10716 PetscCall(PetscFree(matcolor->rows)); 10717 PetscCall(PetscFree(matcolor->den2sp)); 10718 PetscCall(PetscFree(matcolor->colorforcol)); 10719 PetscCall(PetscFree(matcolor->columns)); 10720 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10721 PetscCall(PetscHeaderDestroy(c)); 10722 PetscFunctionReturn(PETSC_SUCCESS); 10723 } 10724 10725 /*@C 10726 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10727 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10728 `MatTransposeColoring` to sparse `B`. 10729 10730 Collective 10731 10732 Input Parameters: 10733 + coloring - coloring context created with `MatTransposeColoringCreate()` 10734 - B - sparse matrix 10735 10736 Output Parameter: 10737 . Btdense - dense matrix $B^T$ 10738 10739 Level: developer 10740 10741 Note: 10742 These are used internally for some implementations of `MatRARt()` 10743 10744 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10745 @*/ 10746 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10747 { 10748 PetscFunctionBegin; 10749 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10750 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10751 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10752 10753 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10754 PetscFunctionReturn(PETSC_SUCCESS); 10755 } 10756 10757 /*@C 10758 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10759 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10760 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10761 $C_{sp}$ from $C_{den}$. 10762 10763 Collective 10764 10765 Input Parameters: 10766 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10767 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10768 10769 Output Parameter: 10770 . Csp - sparse matrix 10771 10772 Level: developer 10773 10774 Note: 10775 These are used internally for some implementations of `MatRARt()` 10776 10777 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10778 @*/ 10779 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10780 { 10781 PetscFunctionBegin; 10782 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10783 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10784 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10785 10786 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10787 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10788 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10789 PetscFunctionReturn(PETSC_SUCCESS); 10790 } 10791 10792 /*@C 10793 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10794 10795 Collective 10796 10797 Input Parameters: 10798 + mat - the matrix product C 10799 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10800 10801 Output Parameter: 10802 . color - the new coloring context 10803 10804 Level: intermediate 10805 10806 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10807 `MatTransColoringApplyDenToSp()` 10808 @*/ 10809 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10810 { 10811 MatTransposeColoring c; 10812 MPI_Comm comm; 10813 10814 PetscFunctionBegin; 10815 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10816 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10817 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10818 10819 c->ctype = iscoloring->ctype; 10820 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10821 10822 *color = c; 10823 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10824 PetscFunctionReturn(PETSC_SUCCESS); 10825 } 10826 10827 /*@ 10828 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10829 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10830 same, otherwise it will be larger 10831 10832 Not Collective 10833 10834 Input Parameter: 10835 . mat - the matrix 10836 10837 Output Parameter: 10838 . state - the current state 10839 10840 Level: intermediate 10841 10842 Notes: 10843 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10844 different matrices 10845 10846 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10847 10848 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10849 10850 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10851 @*/ 10852 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10853 { 10854 PetscFunctionBegin; 10855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10856 *state = mat->nonzerostate; 10857 PetscFunctionReturn(PETSC_SUCCESS); 10858 } 10859 10860 /*@ 10861 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10862 matrices from each processor 10863 10864 Collective 10865 10866 Input Parameters: 10867 + comm - the communicators the parallel matrix will live on 10868 . seqmat - the input sequential matrices 10869 . n - number of local columns (or `PETSC_DECIDE`) 10870 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10871 10872 Output Parameter: 10873 . mpimat - the parallel matrix generated 10874 10875 Level: developer 10876 10877 Note: 10878 The number of columns of the matrix in EACH processor MUST be the same. 10879 10880 .seealso: [](ch_matrices), `Mat` 10881 @*/ 10882 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10883 { 10884 PetscMPIInt size; 10885 10886 PetscFunctionBegin; 10887 PetscCallMPI(MPI_Comm_size(comm, &size)); 10888 if (size == 1) { 10889 if (reuse == MAT_INITIAL_MATRIX) { 10890 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10891 } else { 10892 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10893 } 10894 PetscFunctionReturn(PETSC_SUCCESS); 10895 } 10896 10897 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"); 10898 10899 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10900 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10901 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10902 PetscFunctionReturn(PETSC_SUCCESS); 10903 } 10904 10905 /*@ 10906 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10907 10908 Collective 10909 10910 Input Parameters: 10911 + A - the matrix to create subdomains from 10912 - N - requested number of subdomains 10913 10914 Output Parameters: 10915 + n - number of subdomains resulting on this MPI process 10916 - iss - `IS` list with indices of subdomains on this MPI process 10917 10918 Level: advanced 10919 10920 Note: 10921 The number of subdomains must be smaller than the communicator size 10922 10923 .seealso: [](ch_matrices), `Mat`, `IS` 10924 @*/ 10925 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10926 { 10927 MPI_Comm comm, subcomm; 10928 PetscMPIInt size, rank, color; 10929 PetscInt rstart, rend, k; 10930 10931 PetscFunctionBegin; 10932 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10933 PetscCallMPI(MPI_Comm_size(comm, &size)); 10934 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10935 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); 10936 *n = 1; 10937 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10938 color = rank / k; 10939 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10940 PetscCall(PetscMalloc1(1, iss)); 10941 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10942 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10943 PetscCallMPI(MPI_Comm_free(&subcomm)); 10944 PetscFunctionReturn(PETSC_SUCCESS); 10945 } 10946 10947 /*@ 10948 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10949 10950 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10951 If they are not the same, uses `MatMatMatMult()`. 10952 10953 Once the coarse grid problem is constructed, correct for interpolation operators 10954 that are not of full rank, which can legitimately happen in the case of non-nested 10955 geometric multigrid. 10956 10957 Input Parameters: 10958 + restrct - restriction operator 10959 . dA - fine grid matrix 10960 . interpolate - interpolation operator 10961 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10962 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10963 10964 Output Parameter: 10965 . A - the Galerkin coarse matrix 10966 10967 Options Database Key: 10968 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10969 10970 Level: developer 10971 10972 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10973 @*/ 10974 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10975 { 10976 IS zerorows; 10977 Vec diag; 10978 10979 PetscFunctionBegin; 10980 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10981 /* Construct the coarse grid matrix */ 10982 if (interpolate == restrct) { 10983 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10984 } else { 10985 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10986 } 10987 10988 /* If the interpolation matrix is not of full rank, A will have zero rows. 10989 This can legitimately happen in the case of non-nested geometric multigrid. 10990 In that event, we set the rows of the matrix to the rows of the identity, 10991 ignoring the equations (as the RHS will also be zero). */ 10992 10993 PetscCall(MatFindZeroRows(*A, &zerorows)); 10994 10995 if (zerorows != NULL) { /* if there are any zero rows */ 10996 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10997 PetscCall(MatGetDiagonal(*A, diag)); 10998 PetscCall(VecISSet(diag, zerorows, 1.0)); 10999 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11000 PetscCall(VecDestroy(&diag)); 11001 PetscCall(ISDestroy(&zerorows)); 11002 } 11003 PetscFunctionReturn(PETSC_SUCCESS); 11004 } 11005 11006 /*@C 11007 MatSetOperation - Allows user to set a matrix operation for any matrix type 11008 11009 Logically Collective 11010 11011 Input Parameters: 11012 + mat - the matrix 11013 . op - the name of the operation 11014 - f - the function that provides the operation 11015 11016 Level: developer 11017 11018 Example Usage: 11019 .vb 11020 extern PetscErrorCode usermult(Mat, Vec, Vec); 11021 11022 PetscCall(MatCreateXXX(comm, ..., &A)); 11023 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 11024 .ve 11025 11026 Notes: 11027 See the file `include/petscmat.h` for a complete list of matrix 11028 operations, which all have the form MATOP_<OPERATION>, where 11029 <OPERATION> is the name (in all capital letters) of the 11030 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11031 11032 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11033 sequence as the usual matrix interface routines, since they 11034 are intended to be accessed via the usual matrix interface 11035 routines, e.g., 11036 .vb 11037 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11038 .ve 11039 11040 In particular each function MUST return `PETSC_SUCCESS` on success and 11041 nonzero on failure. 11042 11043 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11044 11045 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11046 @*/ 11047 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11048 { 11049 PetscFunctionBegin; 11050 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11051 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11052 (((void (**)(void))mat->ops)[op]) = f; 11053 PetscFunctionReturn(PETSC_SUCCESS); 11054 } 11055 11056 /*@C 11057 MatGetOperation - Gets a matrix operation for any matrix type. 11058 11059 Not Collective 11060 11061 Input Parameters: 11062 + mat - the matrix 11063 - op - the name of the operation 11064 11065 Output Parameter: 11066 . f - the function that provides the operation 11067 11068 Level: developer 11069 11070 Example Usage: 11071 .vb 11072 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11073 11074 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11075 .ve 11076 11077 Notes: 11078 See the file include/petscmat.h for a complete list of matrix 11079 operations, which all have the form MATOP_<OPERATION>, where 11080 <OPERATION> is the name (in all capital letters) of the 11081 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11082 11083 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11084 11085 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11086 @*/ 11087 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11088 { 11089 PetscFunctionBegin; 11090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11091 *f = (((void (**)(void))mat->ops)[op]); 11092 PetscFunctionReturn(PETSC_SUCCESS); 11093 } 11094 11095 /*@ 11096 MatHasOperation - Determines whether the given matrix supports the particular operation. 11097 11098 Not Collective 11099 11100 Input Parameters: 11101 + mat - the matrix 11102 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11103 11104 Output Parameter: 11105 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11106 11107 Level: advanced 11108 11109 Note: 11110 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11111 11112 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11113 @*/ 11114 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11115 { 11116 PetscFunctionBegin; 11117 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11118 PetscAssertPointer(has, 3); 11119 if (mat->ops->hasoperation) { 11120 PetscUseTypeMethod(mat, hasoperation, op, has); 11121 } else { 11122 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11123 else { 11124 *has = PETSC_FALSE; 11125 if (op == MATOP_CREATE_SUBMATRIX) { 11126 PetscMPIInt size; 11127 11128 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11129 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11130 } 11131 } 11132 } 11133 PetscFunctionReturn(PETSC_SUCCESS); 11134 } 11135 11136 /*@ 11137 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11138 11139 Collective 11140 11141 Input Parameter: 11142 . mat - the matrix 11143 11144 Output Parameter: 11145 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11146 11147 Level: beginner 11148 11149 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11150 @*/ 11151 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11152 { 11153 PetscFunctionBegin; 11154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11155 PetscValidType(mat, 1); 11156 PetscAssertPointer(cong, 2); 11157 if (!mat->rmap || !mat->cmap) { 11158 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11159 PetscFunctionReturn(PETSC_SUCCESS); 11160 } 11161 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11162 PetscCall(PetscLayoutSetUp(mat->rmap)); 11163 PetscCall(PetscLayoutSetUp(mat->cmap)); 11164 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11165 if (*cong) mat->congruentlayouts = 1; 11166 else mat->congruentlayouts = 0; 11167 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11168 PetscFunctionReturn(PETSC_SUCCESS); 11169 } 11170 11171 PetscErrorCode MatSetInf(Mat A) 11172 { 11173 PetscFunctionBegin; 11174 PetscUseTypeMethod(A, setinf); 11175 PetscFunctionReturn(PETSC_SUCCESS); 11176 } 11177 11178 /*@C 11179 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 11180 and possibly removes small values from the graph structure. 11181 11182 Collective 11183 11184 Input Parameters: 11185 + A - the matrix 11186 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11187 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11188 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11189 . num_idx - size of 'index' array 11190 - index - array of block indices to use for graph strength of connection weight 11191 11192 Output Parameter: 11193 . graph - the resulting graph 11194 11195 Level: advanced 11196 11197 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11198 @*/ 11199 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11200 { 11201 PetscFunctionBegin; 11202 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11203 PetscValidType(A, 1); 11204 PetscValidLogicalCollectiveBool(A, scale, 3); 11205 PetscAssertPointer(graph, 7); 11206 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11207 PetscFunctionReturn(PETSC_SUCCESS); 11208 } 11209 11210 /*@ 11211 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11212 meaning the same memory is used for the matrix, and no new memory is allocated. 11213 11214 Collective 11215 11216 Input Parameters: 11217 + A - the matrix 11218 - 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 11219 11220 Level: intermediate 11221 11222 Developer Note: 11223 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11224 of the arrays in the data structure are unneeded. 11225 11226 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11227 @*/ 11228 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11229 { 11230 PetscFunctionBegin; 11231 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11232 PetscUseTypeMethod(A, eliminatezeros, keep); 11233 PetscFunctionReturn(PETSC_SUCCESS); 11234 } 11235