1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetSize(mat, &N, NULL)); 207 PetscCall(MatGetLocalSize(mat, &n, NULL)); 208 PetscCall(VecSet(l, 0.0)); 209 PetscCall(VecSetRandom(r, NULL)); 210 PetscCall(MatMult(mat, r, l)); 211 PetscCall(VecGetArrayRead(l, &al)); 212 } else { /* nonzero columns */ 213 PetscCall(MatGetSize(mat, NULL, &N)); 214 PetscCall(MatGetLocalSize(mat, NULL, &n)); 215 PetscCall(VecSet(r, 0.0)); 216 PetscCall(VecSetRandom(l, NULL)); 217 PetscCall(MatMultTranspose(mat, l, r)); 218 PetscCall(VecGetArrayRead(r, &al)); 219 } 220 if (tol <= 0.0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nz++; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nz++; 226 } 227 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 228 if (gnz != N) { 229 PetscInt *nzr; 230 PetscCall(PetscMalloc1(nz, &nzr)); 231 if (nz) { 232 if (tol < 0) { 233 for (i = 0, nz = 0; i < n; i++) 234 if (al[i] != 0.0) nzr[nz++] = i; 235 } else { 236 for (i = 0, nz = 0; i < n; i++) 237 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 238 } 239 } 240 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 241 } else *nonzero = NULL; 242 if (!cols) { /* nonzero rows */ 243 PetscCall(VecRestoreArrayRead(l, &al)); 244 } else { 245 PetscCall(VecRestoreArrayRead(r, &al)); 246 } 247 PetscCall(VecDestroy(&l)); 248 PetscCall(VecDestroy(&r)); 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 /*@ 253 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 254 255 Input Parameter: 256 . mat - the matrix 257 258 Output Parameter: 259 . keptrows - the rows that are not completely zero 260 261 Level: intermediate 262 263 Note: 264 `keptrows` is set to `NULL` if all rows are nonzero. 265 266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 267 @*/ 268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 269 { 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 272 PetscValidType(mat, 1); 273 PetscAssertPointer(keptrows, 2); 274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 276 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 277 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 278 PetscFunctionReturn(PETSC_SUCCESS); 279 } 280 281 /*@ 282 MatFindZeroRows - Locate all rows that are completely zero in the matrix 283 284 Input Parameter: 285 . mat - the matrix 286 287 Output Parameter: 288 . zerorows - the rows that are completely zero 289 290 Level: intermediate 291 292 Note: 293 `zerorows` is set to `NULL` if no rows are zero. 294 295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 296 @*/ 297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 298 { 299 IS keptrows; 300 PetscInt m, n; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 304 PetscValidType(mat, 1); 305 PetscAssertPointer(zerorows, 2); 306 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 307 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 308 In keeping with this convention, we set zerorows to NULL if there are no zero 309 rows. */ 310 if (keptrows == NULL) { 311 *zerorows = NULL; 312 } else { 313 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 314 PetscCall(ISComplement(keptrows, m, n, zerorows)); 315 PetscCall(ISDestroy(&keptrows)); 316 } 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 322 323 Not Collective 324 325 Input Parameter: 326 . A - the matrix 327 328 Output Parameter: 329 . a - the diagonal part (which is a SEQUENTIAL matrix) 330 331 Level: advanced 332 333 Notes: 334 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 335 336 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 337 338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 339 @*/ 340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 344 PetscValidType(A, 1); 345 PetscAssertPointer(a, 2); 346 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 347 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 348 else { 349 PetscMPIInt size; 350 351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 352 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 353 *a = A; 354 } 355 PetscFunctionReturn(PETSC_SUCCESS); 356 } 357 358 /*@ 359 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 360 361 Collective 362 363 Input Parameter: 364 . mat - the matrix 365 366 Output Parameter: 367 . trace - the sum of the diagonal entries 368 369 Level: advanced 370 371 .seealso: [](ch_matrices), `Mat` 372 @*/ 373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 374 { 375 Vec diag; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 379 PetscAssertPointer(trace, 2); 380 PetscCall(MatCreateVecs(mat, &diag, NULL)); 381 PetscCall(MatGetDiagonal(mat, diag)); 382 PetscCall(VecSum(diag, trace)); 383 PetscCall(VecDestroy(&diag)); 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 /*@ 388 MatRealPart - Zeros out the imaginary part of the matrix 389 390 Logically Collective 391 392 Input Parameter: 393 . mat - the matrix 394 395 Level: advanced 396 397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 398 @*/ 399 PetscErrorCode MatRealPart(Mat mat) 400 { 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 403 PetscValidType(mat, 1); 404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406 MatCheckPreallocated(mat, 1); 407 PetscUseTypeMethod(mat, realpart); 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 /*@C 412 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 413 414 Collective 415 416 Input Parameter: 417 . mat - the matrix 418 419 Output Parameters: 420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 421 - ghosts - the global indices of the ghost points 422 423 Level: advanced 424 425 Note: 426 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 427 428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 429 @*/ 430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 431 { 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 434 PetscValidType(mat, 1); 435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 437 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 438 else { 439 if (nghosts) *nghosts = 0; 440 if (ghosts) *ghosts = NULL; 441 } 442 PetscFunctionReturn(PETSC_SUCCESS); 443 } 444 445 /*@ 446 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 447 448 Logically Collective 449 450 Input Parameter: 451 . mat - the matrix 452 453 Level: advanced 454 455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 456 @*/ 457 PetscErrorCode MatImaginaryPart(Mat mat) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 461 PetscValidType(mat, 1); 462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 464 MatCheckPreallocated(mat, 1); 465 PetscUseTypeMethod(mat, imaginarypart); 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 /*@ 470 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 471 472 Not Collective 473 474 Input Parameter: 475 . mat - the matrix 476 477 Output Parameters: 478 + missing - is any diagonal entry missing 479 - dd - first diagonal entry that is missing (optional) on this process 480 481 Level: advanced 482 483 Note: 484 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 485 486 .seealso: [](ch_matrices), `Mat` 487 @*/ 488 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 489 { 490 PetscFunctionBegin; 491 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 492 PetscValidType(mat, 1); 493 PetscAssertPointer(missing, 2); 494 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 495 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 496 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 497 PetscFunctionReturn(PETSC_SUCCESS); 498 } 499 500 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 501 /*@C 502 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 503 for each row that you get to ensure that your application does 504 not bleed memory. 505 506 Not Collective 507 508 Input Parameters: 509 + mat - the matrix 510 - row - the row to get 511 512 Output Parameters: 513 + ncols - if not `NULL`, the number of nonzeros in `row` 514 . cols - if not `NULL`, the column numbers 515 - vals - if not `NULL`, the numerical values 516 517 Level: advanced 518 519 Notes: 520 This routine is provided for people who need to have direct access 521 to the structure of a matrix. We hope that we provide enough 522 high-level matrix routines that few users will need it. 523 524 `MatGetRow()` always returns 0-based column indices, regardless of 525 whether the internal representation is 0-based (default) or 1-based. 526 527 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 528 not wish to extract these quantities. 529 530 The user can only examine the values extracted with `MatGetRow()`; 531 the values CANNOT be altered. To change the matrix entries, one 532 must use `MatSetValues()`. 533 534 You can only have one call to `MatGetRow()` outstanding for a particular 535 matrix at a time, per processor. `MatGetRow()` can only obtain rows 536 associated with the given processor, it cannot get rows from the 537 other processors; for that we suggest using `MatCreateSubMatrices()`, then 538 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 539 is in the global number of rows. 540 541 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 542 543 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 544 545 Fortran Note: 546 The calling sequence is 547 .vb 548 MatGetRow(matrix,row,ncols,cols,values,ierr) 549 Mat matrix (input) 550 integer row (input) 551 integer ncols (output) 552 integer cols(maxcols) (output) 553 double precision (or double complex) values(maxcols) output 554 .ve 555 where maxcols >= maximum nonzeros in any row of the matrix. 556 557 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 558 @*/ 559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 560 { 561 PetscInt incols; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 565 PetscValidType(mat, 1); 566 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 567 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 568 MatCheckPreallocated(mat, 1); 569 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 570 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 571 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 572 if (ncols) *ncols = incols; 573 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 574 PetscFunctionReturn(PETSC_SUCCESS); 575 } 576 577 /*@ 578 MatConjugate - replaces the matrix values with their complex conjugates 579 580 Logically Collective 581 582 Input Parameter: 583 . mat - the matrix 584 585 Level: advanced 586 587 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 588 @*/ 589 PetscErrorCode MatConjugate(Mat mat) 590 { 591 PetscFunctionBegin; 592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 594 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 595 PetscUseTypeMethod(mat, conjugate); 596 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 597 } 598 PetscFunctionReturn(PETSC_SUCCESS); 599 } 600 601 /*@C 602 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 603 604 Not Collective 605 606 Input Parameters: 607 + mat - the matrix 608 . row - the row to get 609 . ncols - the number of nonzeros 610 . cols - the columns of the nonzeros 611 - vals - if nonzero the column values 612 613 Level: advanced 614 615 Notes: 616 This routine should be called after you have finished examining the entries. 617 618 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 619 us of the array after it has been restored. If you pass `NULL`, it will 620 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 621 622 Fortran Notes: 623 The calling sequence is 624 .vb 625 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 626 Mat matrix (input) 627 integer row (input) 628 integer ncols (output) 629 integer cols(maxcols) (output) 630 double precision (or double complex) values(maxcols) output 631 .ve 632 Where maxcols >= maximum nonzeros in any row of the matrix. 633 634 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 635 before another call to `MatGetRow()` can be made. 636 637 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 638 @*/ 639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 640 { 641 PetscFunctionBegin; 642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 643 if (ncols) PetscAssertPointer(ncols, 3); 644 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 645 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 646 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 647 if (ncols) *ncols = 0; 648 if (cols) *cols = NULL; 649 if (vals) *vals = NULL; 650 PetscFunctionReturn(PETSC_SUCCESS); 651 } 652 653 /*@ 654 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 655 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 656 657 Not Collective 658 659 Input Parameter: 660 . mat - the matrix 661 662 Level: advanced 663 664 Note: 665 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 666 667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 668 @*/ 669 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 670 { 671 PetscFunctionBegin; 672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 673 PetscValidType(mat, 1); 674 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 675 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 676 MatCheckPreallocated(mat, 1); 677 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 678 PetscUseTypeMethod(mat, getrowuppertriangular); 679 PetscFunctionReturn(PETSC_SUCCESS); 680 } 681 682 /*@ 683 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 684 685 Not Collective 686 687 Input Parameter: 688 . mat - the matrix 689 690 Level: advanced 691 692 Note: 693 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 694 695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 696 @*/ 697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 698 { 699 PetscFunctionBegin; 700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 701 PetscValidType(mat, 1); 702 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 703 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 704 MatCheckPreallocated(mat, 1); 705 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 706 PetscUseTypeMethod(mat, restorerowuppertriangular); 707 PetscFunctionReturn(PETSC_SUCCESS); 708 } 709 710 /*@C 711 MatSetOptionsPrefix - Sets the prefix used for searching for all 712 `Mat` options in the database. 713 714 Logically Collective 715 716 Input Parameters: 717 + A - the matrix 718 - prefix - the prefix to prepend to all option names 719 720 Level: advanced 721 722 Notes: 723 A hyphen (-) must NOT be given at the beginning of the prefix name. 724 The first character of all runtime options is AUTOMATICALLY the hyphen. 725 726 This is NOT used for options for the factorization of the matrix. Normally the 727 prefix is automatically passed in from the PC calling the factorization. To set 728 it directly use `MatSetOptionsPrefixFactor()` 729 730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 731 @*/ 732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 733 { 734 PetscFunctionBegin; 735 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 736 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 737 PetscFunctionReturn(PETSC_SUCCESS); 738 } 739 740 /*@C 741 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 742 for matrices created with `MatGetFactor()` 743 744 Logically Collective 745 746 Input Parameters: 747 + A - the matrix 748 - prefix - the prefix to prepend to all option names for the factored matrix 749 750 Level: developer 751 752 Notes: 753 A hyphen (-) must NOT be given at the beginning of the prefix name. 754 The first character of all runtime options is AUTOMATICALLY the hyphen. 755 756 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 757 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 758 759 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 760 @*/ 761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 762 { 763 PetscFunctionBegin; 764 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 765 if (prefix) { 766 PetscAssertPointer(prefix, 2); 767 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 768 if (prefix != A->factorprefix) { 769 PetscCall(PetscFree(A->factorprefix)); 770 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 771 } 772 } else PetscCall(PetscFree(A->factorprefix)); 773 PetscFunctionReturn(PETSC_SUCCESS); 774 } 775 776 /*@C 777 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 778 for matrices created with `MatGetFactor()` 779 780 Logically Collective 781 782 Input Parameters: 783 + A - the matrix 784 - prefix - the prefix to prepend to all option names for the factored matrix 785 786 Level: developer 787 788 Notes: 789 A hyphen (-) must NOT be given at the beginning of the prefix name. 790 The first character of all runtime options is AUTOMATICALLY the hyphen. 791 792 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 793 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 794 795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 796 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 797 `MatSetOptionsPrefix()` 798 @*/ 799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 800 { 801 size_t len1, len2, new_len; 802 803 PetscFunctionBegin; 804 PetscValidHeader(A, 1); 805 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 806 if (!A->factorprefix) { 807 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 808 PetscFunctionReturn(PETSC_SUCCESS); 809 } 810 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 811 812 PetscCall(PetscStrlen(A->factorprefix, &len1)); 813 PetscCall(PetscStrlen(prefix, &len2)); 814 new_len = len1 + len2 + 1; 815 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 816 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 817 PetscFunctionReturn(PETSC_SUCCESS); 818 } 819 820 /*@C 821 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 822 matrix options in the database. 823 824 Logically Collective 825 826 Input Parameters: 827 + A - the matrix 828 - prefix - the prefix to prepend to all option names 829 830 Level: advanced 831 832 Note: 833 A hyphen (-) must NOT be given at the beginning of the prefix name. 834 The first character of all runtime options is AUTOMATICALLY the hyphen. 835 836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 837 @*/ 838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 839 { 840 PetscFunctionBegin; 841 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 842 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 843 PetscFunctionReturn(PETSC_SUCCESS); 844 } 845 846 /*@C 847 MatGetOptionsPrefix - Gets the prefix used for searching for all 848 matrix options in the database. 849 850 Not Collective 851 852 Input Parameter: 853 . A - the matrix 854 855 Output Parameter: 856 . prefix - pointer to the prefix string used 857 858 Level: advanced 859 860 Fortran Note: 861 The user should pass in a string `prefix` of 862 sufficient length to hold the prefix. 863 864 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 865 @*/ 866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 867 { 868 PetscFunctionBegin; 869 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 870 PetscAssertPointer(prefix, 2); 871 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 872 PetscFunctionReturn(PETSC_SUCCESS); 873 } 874 875 /*@ 876 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 877 878 Collective 879 880 Input Parameter: 881 . A - the matrix 882 883 Level: beginner 884 885 Notes: 886 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 887 888 Users can reset the preallocation to access the original memory. 889 890 Currently only supported for `MATAIJ` matrices. 891 892 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 893 @*/ 894 PetscErrorCode MatResetPreallocation(Mat A) 895 { 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 898 PetscValidType(A, 1); 899 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 900 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 901 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 902 PetscFunctionReturn(PETSC_SUCCESS); 903 } 904 905 /*@ 906 MatSetUp - Sets up the internal matrix data structures for later use. 907 908 Collective 909 910 Input Parameter: 911 . A - the matrix 912 913 Level: intermediate 914 915 Notes: 916 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 917 setting values in the matrix. 918 919 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 920 921 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 922 @*/ 923 PetscErrorCode MatSetUp(Mat A) 924 { 925 PetscFunctionBegin; 926 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 927 if (!((PetscObject)A)->type_name) { 928 PetscMPIInt size; 929 930 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 931 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 932 } 933 if (!A->preallocated) PetscTryTypeMethod(A, setup); 934 PetscCall(PetscLayoutSetUp(A->rmap)); 935 PetscCall(PetscLayoutSetUp(A->cmap)); 936 A->preallocated = PETSC_TRUE; 937 PetscFunctionReturn(PETSC_SUCCESS); 938 } 939 940 #if defined(PETSC_HAVE_SAWS) 941 #include <petscviewersaws.h> 942 #endif 943 944 /* 945 If threadsafety is on extraneous matrices may be printed 946 947 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 948 */ 949 #if !defined(PETSC_HAVE_THREADSAFETY) 950 static PetscInt insidematview = 0; 951 #endif 952 953 /*@C 954 MatViewFromOptions - View properties of the matrix based on options set in the options database 955 956 Collective 957 958 Input Parameters: 959 + A - the matrix 960 . obj - optional additional object that provides the options prefix to use 961 - name - command line option 962 963 Options Database Key: 964 . -mat_view [viewertype]:... - the viewer and its options 965 966 Level: intermediate 967 968 Note: 969 .vb 970 If no value is provided ascii:stdout is used 971 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 972 for example ascii::ascii_info prints just the information about the object not all details 973 unless :append is given filename opens in write mode, overwriting what was already there 974 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 975 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 976 socket[:port] defaults to the standard output port 977 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 978 .ve 979 980 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 981 @*/ 982 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 983 { 984 PetscFunctionBegin; 985 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 986 #if !defined(PETSC_HAVE_THREADSAFETY) 987 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 988 #endif 989 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 990 PetscFunctionReturn(PETSC_SUCCESS); 991 } 992 993 /*@C 994 MatView - display information about a matrix in a variety ways 995 996 Collective 997 998 Input Parameters: 999 + mat - the matrix 1000 - viewer - visualization context 1001 1002 Options Database Keys: 1003 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1004 . -mat_view ::ascii_info_detail - Prints more detailed info 1005 . -mat_view - Prints matrix in ASCII format 1006 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1007 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1008 . -display <name> - Sets display name (default is host) 1009 . -draw_pause <sec> - Sets number of seconds to pause after display 1010 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1011 . -viewer_socket_machine <machine> - - 1012 . -viewer_socket_port <port> - - 1013 . -mat_view binary - save matrix to file in binary format 1014 - -viewer_binary_filename <name> - - 1015 1016 Level: beginner 1017 1018 Notes: 1019 The available visualization contexts include 1020 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1021 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1022 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1023 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1024 1025 The user can open alternative visualization contexts with 1026 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1027 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1028 specified file; corresponding input uses `MatLoad()` 1029 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1030 an X window display 1031 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1032 Currently only the `MATSEQDENSE` and `MATAIJ` 1033 matrix types support the Socket viewer. 1034 1035 The user can call `PetscViewerPushFormat()` to specify the output 1036 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1037 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1038 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1039 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1040 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1041 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1042 format common among all matrix types 1043 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1044 format (which is in many cases the same as the default) 1045 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1046 size and structure (not the matrix entries) 1047 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1048 the matrix structure 1049 1050 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1051 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1052 1053 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1054 1055 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1056 viewer is used. 1057 1058 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1059 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1060 1061 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1062 and then use the following mouse functions. 1063 .vb 1064 left mouse: zoom in 1065 middle mouse: zoom out 1066 right mouse: continue with the simulation 1067 .ve 1068 1069 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1070 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1071 @*/ 1072 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1073 { 1074 PetscInt rows, cols, rbs, cbs; 1075 PetscBool isascii, isstring, issaws; 1076 PetscViewerFormat format; 1077 PetscMPIInt size; 1078 1079 PetscFunctionBegin; 1080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1081 PetscValidType(mat, 1); 1082 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1083 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1084 PetscCheckSameComm(mat, 1, viewer, 2); 1085 1086 PetscCall(PetscViewerGetFormat(viewer, &format)); 1087 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1088 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1089 1090 #if !defined(PETSC_HAVE_THREADSAFETY) 1091 insidematview++; 1092 #endif 1093 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1094 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1096 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1097 1098 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1099 if (isascii) { 1100 if (!mat->preallocated) { 1101 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1102 #if !defined(PETSC_HAVE_THREADSAFETY) 1103 insidematview--; 1104 #endif 1105 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1106 PetscFunctionReturn(PETSC_SUCCESS); 1107 } 1108 if (!mat->assembled) { 1109 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1110 #if !defined(PETSC_HAVE_THREADSAFETY) 1111 insidematview--; 1112 #endif 1113 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1114 PetscFunctionReturn(PETSC_SUCCESS); 1115 } 1116 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1117 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1118 MatNullSpace nullsp, transnullsp; 1119 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatGetSize(mat, &rows, &cols)); 1122 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1123 if (rbs != 1 || cbs != 1) { 1124 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1125 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1126 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1127 if (mat->factortype) { 1128 MatSolverType solver; 1129 PetscCall(MatFactorGetSolverType(mat, &solver)); 1130 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1131 } 1132 if (mat->ops->getinfo) { 1133 MatInfo info; 1134 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1135 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1136 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1137 } 1138 PetscCall(MatGetNullSpace(mat, &nullsp)); 1139 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1140 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1141 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1142 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1143 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1144 PetscCall(PetscViewerASCIIPushTab(viewer)); 1145 PetscCall(MatProductView(mat, viewer)); 1146 PetscCall(PetscViewerASCIIPopTab(viewer)); 1147 } 1148 } else if (issaws) { 1149 #if defined(PETSC_HAVE_SAWS) 1150 PetscMPIInt rank; 1151 1152 PetscCall(PetscObjectName((PetscObject)mat)); 1153 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1154 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1155 #endif 1156 } else if (isstring) { 1157 const char *type; 1158 PetscCall(MatGetType(mat, &type)); 1159 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1160 PetscTryTypeMethod(mat, view, viewer); 1161 } 1162 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1163 PetscCall(PetscViewerASCIIPushTab(viewer)); 1164 PetscUseTypeMethod(mat, viewnative, viewer); 1165 PetscCall(PetscViewerASCIIPopTab(viewer)); 1166 } else if (mat->ops->view) { 1167 PetscCall(PetscViewerASCIIPushTab(viewer)); 1168 PetscUseTypeMethod(mat, view, viewer); 1169 PetscCall(PetscViewerASCIIPopTab(viewer)); 1170 } 1171 if (isascii) { 1172 PetscCall(PetscViewerGetFormat(viewer, &format)); 1173 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1174 } 1175 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1176 #if !defined(PETSC_HAVE_THREADSAFETY) 1177 insidematview--; 1178 #endif 1179 PetscFunctionReturn(PETSC_SUCCESS); 1180 } 1181 1182 #if defined(PETSC_USE_DEBUG) 1183 #include <../src/sys/totalview/tv_data_display.h> 1184 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1185 { 1186 TV_add_row("Local rows", "int", &mat->rmap->n); 1187 TV_add_row("Local columns", "int", &mat->cmap->n); 1188 TV_add_row("Global rows", "int", &mat->rmap->N); 1189 TV_add_row("Global columns", "int", &mat->cmap->N); 1190 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1191 return TV_format_OK; 1192 } 1193 #endif 1194 1195 /*@C 1196 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1197 with `MatView()`. The matrix format is determined from the options database. 1198 Generates a parallel MPI matrix if the communicator has more than one 1199 processor. The default matrix type is `MATAIJ`. 1200 1201 Collective 1202 1203 Input Parameters: 1204 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1205 or some related function before a call to `MatLoad()` 1206 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1207 1208 Options Database Keys: 1209 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1210 block size 1211 . -matload_block_size <bs> - set block size 1212 1213 Level: beginner 1214 1215 Notes: 1216 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1217 `Mat` before calling this routine if you wish to set it from the options database. 1218 1219 `MatLoad()` automatically loads into the options database any options 1220 given in the file filename.info where filename is the name of the file 1221 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1222 file will be ignored if you use the -viewer_binary_skip_info option. 1223 1224 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1225 sets the default matrix type AIJ and sets the local and global sizes. 1226 If type and/or size is already set, then the same are used. 1227 1228 In parallel, each processor can load a subset of rows (or the 1229 entire matrix). This routine is especially useful when a large 1230 matrix is stored on disk and only part of it is desired on each 1231 processor. For example, a parallel solver may access only some of 1232 the rows from each processor. The algorithm used here reads 1233 relatively small blocks of data rather than reading the entire 1234 matrix and then subsetting it. 1235 1236 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1237 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1238 or the sequence like 1239 .vb 1240 `PetscViewer` v; 1241 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1242 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1243 `PetscViewerSetFromOptions`(v); 1244 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1245 `PetscViewerFileSetName`(v,"datafile"); 1246 .ve 1247 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1248 $ -viewer_type {binary, hdf5} 1249 1250 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1251 and src/mat/tutorials/ex10.c with the second approach. 1252 1253 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1254 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1255 Multiple objects, both matrices and vectors, can be stored within the same file. 1256 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1257 1258 Most users should not need to know the details of the binary storage 1259 format, since `MatLoad()` and `MatView()` completely hide these details. 1260 But for anyone who is interested, the standard binary matrix storage 1261 format is 1262 1263 .vb 1264 PetscInt MAT_FILE_CLASSID 1265 PetscInt number of rows 1266 PetscInt number of columns 1267 PetscInt total number of nonzeros 1268 PetscInt *number nonzeros in each row 1269 PetscInt *column indices of all nonzeros (starting index is zero) 1270 PetscScalar *values of all nonzeros 1271 .ve 1272 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1273 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1274 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1275 1276 PETSc automatically does the byte swapping for 1277 machines that store the bytes reversed. Thus if you write your own binary 1278 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1279 and `PetscBinaryWrite()` to see how this may be done. 1280 1281 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1282 Each processor's chunk is loaded independently by its owning MPI process. 1283 Multiple objects, both matrices and vectors, can be stored within the same file. 1284 They are looked up by their PetscObject name. 1285 1286 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1287 by default the same structure and naming of the AIJ arrays and column count 1288 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1289 $ save example.mat A b -v7.3 1290 can be directly read by this routine (see Reference 1 for details). 1291 1292 Depending on your MATLAB version, this format might be a default, 1293 otherwise you can set it as default in Preferences. 1294 1295 Unless -nocompression flag is used to save the file in MATLAB, 1296 PETSc must be configured with ZLIB package. 1297 1298 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1299 1300 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1301 1302 Corresponding `MatView()` is not yet implemented. 1303 1304 The loaded matrix is actually a transpose of the original one in MATLAB, 1305 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1306 With this format, matrix is automatically transposed by PETSc, 1307 unless the matrix is marked as SPD or symmetric 1308 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1309 1310 References: 1311 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1312 1313 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1314 @*/ 1315 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1316 { 1317 PetscBool flg; 1318 1319 PetscFunctionBegin; 1320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1321 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1322 1323 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1324 1325 flg = PETSC_FALSE; 1326 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1327 if (flg) { 1328 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1329 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1330 } 1331 flg = PETSC_FALSE; 1332 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1333 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1334 1335 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1336 PetscUseTypeMethod(mat, load, viewer); 1337 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1338 PetscFunctionReturn(PETSC_SUCCESS); 1339 } 1340 1341 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1342 { 1343 Mat_Redundant *redund = *redundant; 1344 1345 PetscFunctionBegin; 1346 if (redund) { 1347 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1348 PetscCall(ISDestroy(&redund->isrow)); 1349 PetscCall(ISDestroy(&redund->iscol)); 1350 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1351 } else { 1352 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1353 PetscCall(PetscFree(redund->sbuf_j)); 1354 PetscCall(PetscFree(redund->sbuf_a)); 1355 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1356 PetscCall(PetscFree(redund->rbuf_j[i])); 1357 PetscCall(PetscFree(redund->rbuf_a[i])); 1358 } 1359 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1360 } 1361 1362 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1363 PetscCall(PetscFree(redund)); 1364 } 1365 PetscFunctionReturn(PETSC_SUCCESS); 1366 } 1367 1368 /*@C 1369 MatDestroy - Frees space taken by a matrix. 1370 1371 Collective 1372 1373 Input Parameter: 1374 . A - the matrix 1375 1376 Level: beginner 1377 1378 Developer Note: 1379 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1380 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1381 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1382 if changes are needed here. 1383 1384 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1385 @*/ 1386 PetscErrorCode MatDestroy(Mat *A) 1387 { 1388 PetscFunctionBegin; 1389 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1390 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1391 if (--((PetscObject)(*A))->refct > 0) { 1392 *A = NULL; 1393 PetscFunctionReturn(PETSC_SUCCESS); 1394 } 1395 1396 /* if memory was published with SAWs then destroy it */ 1397 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1398 PetscTryTypeMethod((*A), destroy); 1399 1400 PetscCall(PetscFree((*A)->factorprefix)); 1401 PetscCall(PetscFree((*A)->defaultvectype)); 1402 PetscCall(PetscFree((*A)->defaultrandtype)); 1403 PetscCall(PetscFree((*A)->bsizes)); 1404 PetscCall(PetscFree((*A)->solvertype)); 1405 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1406 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1407 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1408 PetscCall(MatProductClear(*A)); 1409 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1410 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1411 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1412 PetscCall(MatDestroy(&(*A)->schur)); 1413 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1414 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1415 PetscCall(PetscHeaderDestroy(A)); 1416 PetscFunctionReturn(PETSC_SUCCESS); 1417 } 1418 1419 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1420 /*@C 1421 MatSetValues - Inserts or adds a block of values into a matrix. 1422 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1423 MUST be called after all calls to `MatSetValues()` have been completed. 1424 1425 Not Collective 1426 1427 Input Parameters: 1428 + mat - the matrix 1429 . v - a logically two-dimensional array of values 1430 . m - the number of rows 1431 . idxm - the global indices of the rows 1432 . n - the number of columns 1433 . idxn - the global indices of the columns 1434 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1435 1436 Level: beginner 1437 1438 Notes: 1439 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1440 1441 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1442 options cannot be mixed without intervening calls to the assembly 1443 routines. 1444 1445 `MatSetValues()` uses 0-based row and column numbers in Fortran 1446 as well as in C. 1447 1448 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1449 simply ignored. This allows easily inserting element stiffness matrices 1450 with homogeneous Dirichlet boundary conditions that you don't want represented 1451 in the matrix. 1452 1453 Efficiency Alert: 1454 The routine `MatSetValuesBlocked()` may offer much better efficiency 1455 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1456 1457 Developer Note: 1458 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1459 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1460 1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1462 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1463 @*/ 1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1465 { 1466 PetscFunctionBeginHot; 1467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1468 PetscValidType(mat, 1); 1469 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1470 PetscAssertPointer(idxm, 3); 1471 PetscAssertPointer(idxn, 5); 1472 MatCheckPreallocated(mat, 1); 1473 1474 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1475 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1476 1477 if (PetscDefined(USE_DEBUG)) { 1478 PetscInt i, j; 1479 1480 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1481 for (i = 0; i < m; i++) { 1482 for (j = 0; j < n; j++) { 1483 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1484 #if defined(PETSC_USE_COMPLEX) 1485 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1486 #else 1487 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1488 #endif 1489 } 1490 } 1491 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1492 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1493 } 1494 1495 if (mat->assembled) { 1496 mat->was_assembled = PETSC_TRUE; 1497 mat->assembled = PETSC_FALSE; 1498 } 1499 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1500 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1501 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1502 PetscFunctionReturn(PETSC_SUCCESS); 1503 } 1504 1505 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1506 /*@C 1507 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1508 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1509 MUST be called after all calls to `MatSetValues()` have been completed. 1510 1511 Not Collective 1512 1513 Input Parameters: 1514 + mat - the matrix 1515 . v - a logically two-dimensional array of values 1516 . ism - the rows to provide 1517 . isn - the columns to provide 1518 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1519 1520 Level: beginner 1521 1522 Notes: 1523 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1524 1525 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1526 options cannot be mixed without intervening calls to the assembly 1527 routines. 1528 1529 `MatSetValues()` uses 0-based row and column numbers in Fortran 1530 as well as in C. 1531 1532 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1533 simply ignored. This allows easily inserting element stiffness matrices 1534 with homogeneous Dirichlet boundary conditions that you don't want represented 1535 in the matrix. 1536 1537 Efficiency Alert: 1538 The routine `MatSetValuesBlocked()` may offer much better efficiency 1539 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1540 1541 This is currently not optimized for any particular `ISType` 1542 1543 Developer Note: 1544 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1545 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1546 1547 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1548 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1549 @*/ 1550 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1551 { 1552 PetscInt m, n; 1553 const PetscInt *rows, *cols; 1554 1555 PetscFunctionBeginHot; 1556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1557 PetscCall(ISGetIndices(ism, &rows)); 1558 PetscCall(ISGetIndices(isn, &cols)); 1559 PetscCall(ISGetLocalSize(ism, &m)); 1560 PetscCall(ISGetLocalSize(isn, &n)); 1561 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1562 PetscCall(ISRestoreIndices(ism, &rows)); 1563 PetscCall(ISRestoreIndices(isn, &cols)); 1564 PetscFunctionReturn(PETSC_SUCCESS); 1565 } 1566 1567 /*@ 1568 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1569 values into a matrix 1570 1571 Not Collective 1572 1573 Input Parameters: 1574 + mat - the matrix 1575 . row - the (block) row to set 1576 - v - a logically two-dimensional array of values 1577 1578 Level: intermediate 1579 1580 Notes: 1581 The values, `v`, are column-oriented (for the block version) and sorted 1582 1583 All the nonzero values in `row` must be provided 1584 1585 The matrix must have previously had its column indices set, likely by having been assembled. 1586 1587 `row` must belong to this MPI process 1588 1589 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1590 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1591 @*/ 1592 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1593 { 1594 PetscInt globalrow; 1595 1596 PetscFunctionBegin; 1597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1598 PetscValidType(mat, 1); 1599 PetscAssertPointer(v, 3); 1600 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1601 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1602 PetscFunctionReturn(PETSC_SUCCESS); 1603 } 1604 1605 /*@ 1606 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1607 values into a matrix 1608 1609 Not Collective 1610 1611 Input Parameters: 1612 + mat - the matrix 1613 . row - the (block) row to set 1614 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1615 1616 Level: advanced 1617 1618 Notes: 1619 The values, `v`, are column-oriented for the block version. 1620 1621 All the nonzeros in `row` must be provided 1622 1623 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1624 1625 `row` must belong to this process 1626 1627 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1628 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1629 @*/ 1630 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1631 { 1632 PetscFunctionBeginHot; 1633 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1634 PetscValidType(mat, 1); 1635 MatCheckPreallocated(mat, 1); 1636 PetscAssertPointer(v, 3); 1637 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1638 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1639 mat->insertmode = INSERT_VALUES; 1640 1641 if (mat->assembled) { 1642 mat->was_assembled = PETSC_TRUE; 1643 mat->assembled = PETSC_FALSE; 1644 } 1645 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1646 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1647 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1648 PetscFunctionReturn(PETSC_SUCCESS); 1649 } 1650 1651 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1652 /*@ 1653 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1654 Using structured grid indexing 1655 1656 Not Collective 1657 1658 Input Parameters: 1659 + mat - the matrix 1660 . m - number of rows being entered 1661 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1662 . n - number of columns being entered 1663 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1664 . v - a logically two-dimensional array of values 1665 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1666 1667 Level: beginner 1668 1669 Notes: 1670 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1671 1672 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1673 options cannot be mixed without intervening calls to the assembly 1674 routines. 1675 1676 The grid coordinates are across the entire grid, not just the local portion 1677 1678 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1679 as well as in C. 1680 1681 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1682 1683 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1684 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1685 1686 The columns and rows in the stencil passed in MUST be contained within the 1687 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1688 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1689 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1690 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1691 1692 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1693 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1694 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1695 `DM_BOUNDARY_PERIODIC` boundary type. 1696 1697 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1698 a single value per point) you can skip filling those indices. 1699 1700 Inspired by the structured grid interface to the HYPRE package 1701 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1702 1703 Efficiency Alert: 1704 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1705 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1706 1707 Fortran Note: 1708 `idxm` and `idxn` should be declared as 1709 $ MatStencil idxm(4,m),idxn(4,n) 1710 and the values inserted using 1711 .vb 1712 idxm(MatStencil_i,1) = i 1713 idxm(MatStencil_j,1) = j 1714 idxm(MatStencil_k,1) = k 1715 idxm(MatStencil_c,1) = c 1716 etc 1717 .ve 1718 1719 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1720 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1721 @*/ 1722 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1723 { 1724 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1725 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1726 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1727 1728 PetscFunctionBegin; 1729 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1730 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1731 PetscValidType(mat, 1); 1732 PetscAssertPointer(idxm, 3); 1733 PetscAssertPointer(idxn, 5); 1734 1735 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1736 jdxm = buf; 1737 jdxn = buf + m; 1738 } else { 1739 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1740 jdxm = bufm; 1741 jdxn = bufn; 1742 } 1743 for (i = 0; i < m; i++) { 1744 for (j = 0; j < 3 - sdim; j++) dxm++; 1745 tmp = *dxm++ - starts[0]; 1746 for (j = 0; j < dim - 1; j++) { 1747 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1748 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1749 } 1750 if (mat->stencil.noc) dxm++; 1751 jdxm[i] = tmp; 1752 } 1753 for (i = 0; i < n; i++) { 1754 for (j = 0; j < 3 - sdim; j++) dxn++; 1755 tmp = *dxn++ - starts[0]; 1756 for (j = 0; j < dim - 1; j++) { 1757 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1758 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1759 } 1760 if (mat->stencil.noc) dxn++; 1761 jdxn[i] = tmp; 1762 } 1763 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1764 PetscCall(PetscFree2(bufm, bufn)); 1765 PetscFunctionReturn(PETSC_SUCCESS); 1766 } 1767 1768 /*@ 1769 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1770 Using structured grid indexing 1771 1772 Not Collective 1773 1774 Input Parameters: 1775 + mat - the matrix 1776 . m - number of rows being entered 1777 . idxm - grid coordinates for matrix rows being entered 1778 . n - number of columns being entered 1779 . idxn - grid coordinates for matrix columns being entered 1780 . v - a logically two-dimensional array of values 1781 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1782 1783 Level: beginner 1784 1785 Notes: 1786 By default the values, `v`, are row-oriented and unsorted. 1787 See `MatSetOption()` for other options. 1788 1789 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1790 options cannot be mixed without intervening calls to the assembly 1791 routines. 1792 1793 The grid coordinates are across the entire grid, not just the local portion 1794 1795 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1796 as well as in C. 1797 1798 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1799 1800 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1801 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1802 1803 The columns and rows in the stencil passed in MUST be contained within the 1804 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1805 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1806 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1807 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1808 1809 Negative indices may be passed in idxm and idxn, these rows and columns are 1810 simply ignored. This allows easily inserting element stiffness matrices 1811 with homogeneous Dirichlet boundary conditions that you don't want represented 1812 in the matrix. 1813 1814 Inspired by the structured grid interface to the HYPRE package 1815 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1816 1817 Fortran Note: 1818 `idxm` and `idxn` should be declared as 1819 $ MatStencil idxm(4,m),idxn(4,n) 1820 and the values inserted using 1821 .vb 1822 idxm(MatStencil_i,1) = i 1823 idxm(MatStencil_j,1) = j 1824 idxm(MatStencil_k,1) = k 1825 etc 1826 .ve 1827 1828 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1829 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1830 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1831 @*/ 1832 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1833 { 1834 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1835 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1836 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1837 1838 PetscFunctionBegin; 1839 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1840 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1841 PetscValidType(mat, 1); 1842 PetscAssertPointer(idxm, 3); 1843 PetscAssertPointer(idxn, 5); 1844 PetscAssertPointer(v, 6); 1845 1846 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1847 jdxm = buf; 1848 jdxn = buf + m; 1849 } else { 1850 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1851 jdxm = bufm; 1852 jdxn = bufn; 1853 } 1854 for (i = 0; i < m; i++) { 1855 for (j = 0; j < 3 - sdim; j++) dxm++; 1856 tmp = *dxm++ - starts[0]; 1857 for (j = 0; j < sdim - 1; j++) { 1858 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1859 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1860 } 1861 dxm++; 1862 jdxm[i] = tmp; 1863 } 1864 for (i = 0; i < n; i++) { 1865 for (j = 0; j < 3 - sdim; j++) dxn++; 1866 tmp = *dxn++ - starts[0]; 1867 for (j = 0; j < sdim - 1; j++) { 1868 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1869 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1870 } 1871 dxn++; 1872 jdxn[i] = tmp; 1873 } 1874 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1875 PetscCall(PetscFree2(bufm, bufn)); 1876 PetscFunctionReturn(PETSC_SUCCESS); 1877 } 1878 1879 /*@ 1880 MatSetStencil - Sets the grid information for setting values into a matrix via 1881 `MatSetValuesStencil()` 1882 1883 Not Collective 1884 1885 Input Parameters: 1886 + mat - the matrix 1887 . dim - dimension of the grid 1, 2, or 3 1888 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1889 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1890 - dof - number of degrees of freedom per node 1891 1892 Level: beginner 1893 1894 Notes: 1895 Inspired by the structured grid interface to the HYPRE package 1896 (www.llnl.gov/CASC/hyper) 1897 1898 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1899 user. 1900 1901 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1902 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1903 @*/ 1904 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1905 { 1906 PetscFunctionBegin; 1907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1908 PetscAssertPointer(dims, 3); 1909 PetscAssertPointer(starts, 4); 1910 1911 mat->stencil.dim = dim + (dof > 1); 1912 for (PetscInt i = 0; i < dim; i++) { 1913 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1914 mat->stencil.starts[i] = starts[dim - i - 1]; 1915 } 1916 mat->stencil.dims[dim] = dof; 1917 mat->stencil.starts[dim] = 0; 1918 mat->stencil.noc = (PetscBool)(dof == 1); 1919 PetscFunctionReturn(PETSC_SUCCESS); 1920 } 1921 1922 /*@C 1923 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1924 1925 Not Collective 1926 1927 Input Parameters: 1928 + mat - the matrix 1929 . v - a logically two-dimensional array of values 1930 . m - the number of block rows 1931 . idxm - the global block indices 1932 . n - the number of block columns 1933 . idxn - the global block indices 1934 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1935 1936 Level: intermediate 1937 1938 Notes: 1939 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1940 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1941 1942 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1943 NOT the total number of rows/columns; for example, if the block size is 2 and 1944 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1945 The values in idxm would be 1 2; that is the first index for each block divided by 1946 the block size. 1947 1948 You must call `MatSetBlockSize()` when constructing this matrix (before 1949 preallocating it). 1950 1951 By default the values, `v`, are row-oriented, so the layout of 1952 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1953 1954 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1955 options cannot be mixed without intervening calls to the assembly 1956 routines. 1957 1958 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1959 as well as in C. 1960 1961 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1962 simply ignored. This allows easily inserting element stiffness matrices 1963 with homogeneous Dirichlet boundary conditions that you don't want represented 1964 in the matrix. 1965 1966 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1967 internal searching must be done to determine where to place the 1968 data in the matrix storage space. By instead inserting blocks of 1969 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1970 reduced. 1971 1972 Example: 1973 .vb 1974 Suppose m=n=2 and block size(bs) = 2 The array is 1975 1976 1 2 | 3 4 1977 5 6 | 7 8 1978 - - - | - - - 1979 9 10 | 11 12 1980 13 14 | 15 16 1981 1982 v[] should be passed in like 1983 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1984 1985 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1986 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1987 .ve 1988 1989 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1990 @*/ 1991 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1992 { 1993 PetscFunctionBeginHot; 1994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1995 PetscValidType(mat, 1); 1996 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1997 PetscAssertPointer(idxm, 3); 1998 PetscAssertPointer(idxn, 5); 1999 MatCheckPreallocated(mat, 1); 2000 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2001 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2002 if (PetscDefined(USE_DEBUG)) { 2003 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2004 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2005 } 2006 if (PetscDefined(USE_DEBUG)) { 2007 PetscInt rbs, cbs, M, N, i; 2008 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2009 PetscCall(MatGetSize(mat, &M, &N)); 2010 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 2011 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 2012 } 2013 if (mat->assembled) { 2014 mat->was_assembled = PETSC_TRUE; 2015 mat->assembled = PETSC_FALSE; 2016 } 2017 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2018 if (mat->ops->setvaluesblocked) { 2019 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2020 } else { 2021 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2022 PetscInt i, j, bs, cbs; 2023 2024 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2025 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2026 iidxm = buf; 2027 iidxn = buf + m * bs; 2028 } else { 2029 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2030 iidxm = bufr; 2031 iidxn = bufc; 2032 } 2033 for (i = 0; i < m; i++) { 2034 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2035 } 2036 if (m != n || bs != cbs || idxm != idxn) { 2037 for (i = 0; i < n; i++) { 2038 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2039 } 2040 } else iidxn = iidxm; 2041 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2042 PetscCall(PetscFree2(bufr, bufc)); 2043 } 2044 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2045 PetscFunctionReturn(PETSC_SUCCESS); 2046 } 2047 2048 /*@C 2049 MatGetValues - Gets a block of local values from a matrix. 2050 2051 Not Collective; can only return values that are owned by the give process 2052 2053 Input Parameters: 2054 + mat - the matrix 2055 . v - a logically two-dimensional array for storing the values 2056 . m - the number of rows 2057 . idxm - the global indices of the rows 2058 . n - the number of columns 2059 - idxn - the global indices of the columns 2060 2061 Level: advanced 2062 2063 Notes: 2064 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2065 The values, `v`, are then returned in a row-oriented format, 2066 analogous to that used by default in `MatSetValues()`. 2067 2068 `MatGetValues()` uses 0-based row and column numbers in 2069 Fortran as well as in C. 2070 2071 `MatGetValues()` requires that the matrix has been assembled 2072 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2073 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2074 without intermediate matrix assembly. 2075 2076 Negative row or column indices will be ignored and those locations in `v` will be 2077 left unchanged. 2078 2079 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2080 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2081 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2082 2083 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2084 @*/ 2085 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2086 { 2087 PetscFunctionBegin; 2088 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2089 PetscValidType(mat, 1); 2090 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2091 PetscAssertPointer(idxm, 3); 2092 PetscAssertPointer(idxn, 5); 2093 PetscAssertPointer(v, 6); 2094 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2095 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2096 MatCheckPreallocated(mat, 1); 2097 2098 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2099 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2100 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2101 PetscFunctionReturn(PETSC_SUCCESS); 2102 } 2103 2104 /*@C 2105 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2106 defined previously by `MatSetLocalToGlobalMapping()` 2107 2108 Not Collective 2109 2110 Input Parameters: 2111 + mat - the matrix 2112 . nrow - number of rows 2113 . irow - the row local indices 2114 . ncol - number of columns 2115 - icol - the column local indices 2116 2117 Output Parameter: 2118 . y - a logically two-dimensional array of values 2119 2120 Level: advanced 2121 2122 Notes: 2123 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2124 2125 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2126 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2127 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2128 with `MatSetLocalToGlobalMapping()`. 2129 2130 Developer Note: 2131 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2132 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2133 2134 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2135 `MatSetValuesLocal()`, `MatGetValues()` 2136 @*/ 2137 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2138 { 2139 PetscFunctionBeginHot; 2140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2141 PetscValidType(mat, 1); 2142 MatCheckPreallocated(mat, 1); 2143 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2144 PetscAssertPointer(irow, 3); 2145 PetscAssertPointer(icol, 5); 2146 if (PetscDefined(USE_DEBUG)) { 2147 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2148 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2149 } 2150 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2151 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2152 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2153 else { 2154 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2155 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2156 irowm = buf; 2157 icolm = buf + nrow; 2158 } else { 2159 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2160 irowm = bufr; 2161 icolm = bufc; 2162 } 2163 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2164 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2165 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2166 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2167 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2168 PetscCall(PetscFree2(bufr, bufc)); 2169 } 2170 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2171 PetscFunctionReturn(PETSC_SUCCESS); 2172 } 2173 2174 /*@ 2175 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2176 the same size. Currently, this can only be called once and creates the given matrix. 2177 2178 Not Collective 2179 2180 Input Parameters: 2181 + mat - the matrix 2182 . nb - the number of blocks 2183 . bs - the number of rows (and columns) in each block 2184 . rows - a concatenation of the rows for each block 2185 - v - a concatenation of logically two-dimensional arrays of values 2186 2187 Level: advanced 2188 2189 Notes: 2190 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2191 2192 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2193 2194 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2195 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2196 @*/ 2197 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2198 { 2199 PetscFunctionBegin; 2200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2201 PetscValidType(mat, 1); 2202 PetscAssertPointer(rows, 4); 2203 PetscAssertPointer(v, 5); 2204 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2205 2206 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2207 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2208 else { 2209 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2210 } 2211 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2212 PetscFunctionReturn(PETSC_SUCCESS); 2213 } 2214 2215 /*@ 2216 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2217 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2218 using a local (per-processor) numbering. 2219 2220 Not Collective 2221 2222 Input Parameters: 2223 + x - the matrix 2224 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2225 - cmapping - column mapping 2226 2227 Level: intermediate 2228 2229 Note: 2230 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2231 2232 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2233 @*/ 2234 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2235 { 2236 PetscFunctionBegin; 2237 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2238 PetscValidType(x, 1); 2239 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2240 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2241 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2242 else { 2243 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2244 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2245 } 2246 PetscFunctionReturn(PETSC_SUCCESS); 2247 } 2248 2249 /*@ 2250 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2251 2252 Not Collective 2253 2254 Input Parameter: 2255 . A - the matrix 2256 2257 Output Parameters: 2258 + rmapping - row mapping 2259 - cmapping - column mapping 2260 2261 Level: advanced 2262 2263 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2264 @*/ 2265 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2266 { 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2269 PetscValidType(A, 1); 2270 if (rmapping) { 2271 PetscAssertPointer(rmapping, 2); 2272 *rmapping = A->rmap->mapping; 2273 } 2274 if (cmapping) { 2275 PetscAssertPointer(cmapping, 3); 2276 *cmapping = A->cmap->mapping; 2277 } 2278 PetscFunctionReturn(PETSC_SUCCESS); 2279 } 2280 2281 /*@ 2282 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2283 2284 Logically Collective 2285 2286 Input Parameters: 2287 + A - the matrix 2288 . rmap - row layout 2289 - cmap - column layout 2290 2291 Level: advanced 2292 2293 Note: 2294 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2295 2296 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2297 @*/ 2298 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2299 { 2300 PetscFunctionBegin; 2301 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2302 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2303 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2304 PetscFunctionReturn(PETSC_SUCCESS); 2305 } 2306 2307 /*@ 2308 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2309 2310 Not Collective 2311 2312 Input Parameter: 2313 . A - the matrix 2314 2315 Output Parameters: 2316 + rmap - row layout 2317 - cmap - column layout 2318 2319 Level: advanced 2320 2321 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2322 @*/ 2323 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2324 { 2325 PetscFunctionBegin; 2326 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2327 PetscValidType(A, 1); 2328 if (rmap) { 2329 PetscAssertPointer(rmap, 2); 2330 *rmap = A->rmap; 2331 } 2332 if (cmap) { 2333 PetscAssertPointer(cmap, 3); 2334 *cmap = A->cmap; 2335 } 2336 PetscFunctionReturn(PETSC_SUCCESS); 2337 } 2338 2339 /*@C 2340 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2341 using a local numbering of the rows and columns. 2342 2343 Not Collective 2344 2345 Input Parameters: 2346 + mat - the matrix 2347 . nrow - number of rows 2348 . irow - the row local indices 2349 . ncol - number of columns 2350 . icol - the column local indices 2351 . y - a logically two-dimensional array of values 2352 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2353 2354 Level: intermediate 2355 2356 Notes: 2357 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2358 2359 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2360 options cannot be mixed without intervening calls to the assembly 2361 routines. 2362 2363 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2364 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2365 2366 Developer Note: 2367 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2368 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2369 2370 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2371 `MatGetValuesLocal()` 2372 @*/ 2373 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2374 { 2375 PetscFunctionBeginHot; 2376 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2377 PetscValidType(mat, 1); 2378 MatCheckPreallocated(mat, 1); 2379 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2380 PetscAssertPointer(irow, 3); 2381 PetscAssertPointer(icol, 5); 2382 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2383 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2384 if (PetscDefined(USE_DEBUG)) { 2385 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2386 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2387 } 2388 2389 if (mat->assembled) { 2390 mat->was_assembled = PETSC_TRUE; 2391 mat->assembled = PETSC_FALSE; 2392 } 2393 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2394 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2395 else { 2396 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2397 const PetscInt *irowm, *icolm; 2398 2399 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2400 bufr = buf; 2401 bufc = buf + nrow; 2402 irowm = bufr; 2403 icolm = bufc; 2404 } else { 2405 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2406 irowm = bufr; 2407 icolm = bufc; 2408 } 2409 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2410 else irowm = irow; 2411 if (mat->cmap->mapping) { 2412 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2413 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2414 } else icolm = irowm; 2415 } else icolm = icol; 2416 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2417 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2418 } 2419 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2420 PetscFunctionReturn(PETSC_SUCCESS); 2421 } 2422 2423 /*@C 2424 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2425 using a local ordering of the nodes a block at a time. 2426 2427 Not Collective 2428 2429 Input Parameters: 2430 + mat - the matrix 2431 . nrow - number of rows 2432 . irow - the row local indices 2433 . ncol - number of columns 2434 . icol - the column local indices 2435 . y - a logically two-dimensional array of values 2436 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2437 2438 Level: intermediate 2439 2440 Notes: 2441 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2442 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2443 2444 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2445 options cannot be mixed without intervening calls to the assembly 2446 routines. 2447 2448 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2449 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2450 2451 Developer Note: 2452 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2453 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2454 2455 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2456 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2457 @*/ 2458 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2459 { 2460 PetscFunctionBeginHot; 2461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2462 PetscValidType(mat, 1); 2463 MatCheckPreallocated(mat, 1); 2464 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2465 PetscAssertPointer(irow, 3); 2466 PetscAssertPointer(icol, 5); 2467 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2468 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2469 if (PetscDefined(USE_DEBUG)) { 2470 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2471 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2472 } 2473 2474 if (mat->assembled) { 2475 mat->was_assembled = PETSC_TRUE; 2476 mat->assembled = PETSC_FALSE; 2477 } 2478 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2479 PetscInt irbs, rbs; 2480 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2481 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2482 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2483 } 2484 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2485 PetscInt icbs, cbs; 2486 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2487 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2488 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2489 } 2490 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2491 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2492 else { 2493 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2494 const PetscInt *irowm, *icolm; 2495 2496 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2497 bufr = buf; 2498 bufc = buf + nrow; 2499 irowm = bufr; 2500 icolm = bufc; 2501 } else { 2502 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2503 irowm = bufr; 2504 icolm = bufc; 2505 } 2506 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2507 else irowm = irow; 2508 if (mat->cmap->mapping) { 2509 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2510 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2511 } else icolm = irowm; 2512 } else icolm = icol; 2513 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2514 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2515 } 2516 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2517 PetscFunctionReturn(PETSC_SUCCESS); 2518 } 2519 2520 /*@ 2521 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2522 2523 Collective 2524 2525 Input Parameters: 2526 + mat - the matrix 2527 - x - the vector to be multiplied 2528 2529 Output Parameter: 2530 . y - the result 2531 2532 Level: developer 2533 2534 Note: 2535 The vectors `x` and `y` cannot be the same. I.e., one cannot 2536 call `MatMultDiagonalBlock`(A,y,y). 2537 2538 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2539 @*/ 2540 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2541 { 2542 PetscFunctionBegin; 2543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2544 PetscValidType(mat, 1); 2545 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2546 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2547 2548 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2549 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2550 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2551 MatCheckPreallocated(mat, 1); 2552 2553 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2554 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2555 PetscFunctionReturn(PETSC_SUCCESS); 2556 } 2557 2558 /*@ 2559 MatMult - Computes the matrix-vector product, $y = Ax$. 2560 2561 Neighbor-wise Collective 2562 2563 Input Parameters: 2564 + mat - the matrix 2565 - x - the vector to be multiplied 2566 2567 Output Parameter: 2568 . y - the result 2569 2570 Level: beginner 2571 2572 Note: 2573 The vectors `x` and `y` cannot be the same. I.e., one cannot 2574 call `MatMult`(A,y,y). 2575 2576 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2577 @*/ 2578 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2579 { 2580 PetscFunctionBegin; 2581 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2582 PetscValidType(mat, 1); 2583 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2584 VecCheckAssembled(x); 2585 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2586 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2587 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2588 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2589 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2590 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2591 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2592 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2593 PetscCall(VecSetErrorIfLocked(y, 3)); 2594 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2595 MatCheckPreallocated(mat, 1); 2596 2597 PetscCall(VecLockReadPush(x)); 2598 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2599 PetscUseTypeMethod(mat, mult, x, y); 2600 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2601 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2602 PetscCall(VecLockReadPop(x)); 2603 PetscFunctionReturn(PETSC_SUCCESS); 2604 } 2605 2606 /*@ 2607 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2608 2609 Neighbor-wise Collective 2610 2611 Input Parameters: 2612 + mat - the matrix 2613 - x - the vector to be multiplied 2614 2615 Output Parameter: 2616 . y - the result 2617 2618 Level: beginner 2619 2620 Notes: 2621 The vectors `x` and `y` cannot be the same. I.e., one cannot 2622 call `MatMultTranspose`(A,y,y). 2623 2624 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2625 use `MatMultHermitianTranspose()` 2626 2627 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2628 @*/ 2629 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2630 { 2631 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2632 2633 PetscFunctionBegin; 2634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2635 PetscValidType(mat, 1); 2636 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2637 VecCheckAssembled(x); 2638 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2639 2640 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2641 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2642 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2643 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2644 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2645 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2646 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2647 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2648 MatCheckPreallocated(mat, 1); 2649 2650 if (!mat->ops->multtranspose) { 2651 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2652 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2653 } else op = mat->ops->multtranspose; 2654 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2655 PetscCall(VecLockReadPush(x)); 2656 PetscCall((*op)(mat, x, y)); 2657 PetscCall(VecLockReadPop(x)); 2658 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2659 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2660 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2661 PetscFunctionReturn(PETSC_SUCCESS); 2662 } 2663 2664 /*@ 2665 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2666 2667 Neighbor-wise Collective 2668 2669 Input Parameters: 2670 + mat - the matrix 2671 - x - the vector to be multiplied 2672 2673 Output Parameter: 2674 . y - the result 2675 2676 Level: beginner 2677 2678 Notes: 2679 The vectors `x` and `y` cannot be the same. I.e., one cannot 2680 call `MatMultHermitianTranspose`(A,y,y). 2681 2682 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2683 2684 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2685 2686 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2687 @*/ 2688 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2689 { 2690 PetscFunctionBegin; 2691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2692 PetscValidType(mat, 1); 2693 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2694 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2695 2696 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2697 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2698 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2699 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2700 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2701 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2702 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2703 MatCheckPreallocated(mat, 1); 2704 2705 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2706 #if defined(PETSC_USE_COMPLEX) 2707 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2708 PetscCall(VecLockReadPush(x)); 2709 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2710 else PetscUseTypeMethod(mat, mult, x, y); 2711 PetscCall(VecLockReadPop(x)); 2712 } else { 2713 Vec w; 2714 PetscCall(VecDuplicate(x, &w)); 2715 PetscCall(VecCopy(x, w)); 2716 PetscCall(VecConjugate(w)); 2717 PetscCall(MatMultTranspose(mat, w, y)); 2718 PetscCall(VecDestroy(&w)); 2719 PetscCall(VecConjugate(y)); 2720 } 2721 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2722 #else 2723 PetscCall(MatMultTranspose(mat, x, y)); 2724 #endif 2725 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2726 PetscFunctionReturn(PETSC_SUCCESS); 2727 } 2728 2729 /*@ 2730 MatMultAdd - Computes $v3 = v2 + A * v1$. 2731 2732 Neighbor-wise Collective 2733 2734 Input Parameters: 2735 + mat - the matrix 2736 . v1 - the vector to be multiplied by `mat` 2737 - v2 - the vector to be added to the result 2738 2739 Output Parameter: 2740 . v3 - the result 2741 2742 Level: beginner 2743 2744 Note: 2745 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2746 call `MatMultAdd`(A,v1,v2,v1). 2747 2748 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2749 @*/ 2750 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2751 { 2752 PetscFunctionBegin; 2753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2754 PetscValidType(mat, 1); 2755 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2756 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2757 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2758 2759 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2760 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2761 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2762 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2763 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2764 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2765 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2766 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2767 MatCheckPreallocated(mat, 1); 2768 2769 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2770 PetscCall(VecLockReadPush(v1)); 2771 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2772 PetscCall(VecLockReadPop(v1)); 2773 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2774 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2775 PetscFunctionReturn(PETSC_SUCCESS); 2776 } 2777 2778 /*@ 2779 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2780 2781 Neighbor-wise Collective 2782 2783 Input Parameters: 2784 + mat - the matrix 2785 . v1 - the vector to be multiplied by the transpose of the matrix 2786 - v2 - the vector to be added to the result 2787 2788 Output Parameter: 2789 . v3 - the result 2790 2791 Level: beginner 2792 2793 Note: 2794 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2795 call `MatMultTransposeAdd`(A,v1,v2,v1). 2796 2797 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2798 @*/ 2799 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2800 { 2801 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2802 2803 PetscFunctionBegin; 2804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2805 PetscValidType(mat, 1); 2806 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2807 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2808 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2809 2810 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2811 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2812 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2813 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2814 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2815 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2816 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2817 MatCheckPreallocated(mat, 1); 2818 2819 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2820 PetscCall(VecLockReadPush(v1)); 2821 PetscCall((*op)(mat, v1, v2, v3)); 2822 PetscCall(VecLockReadPop(v1)); 2823 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2824 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2825 PetscFunctionReturn(PETSC_SUCCESS); 2826 } 2827 2828 /*@ 2829 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2830 2831 Neighbor-wise Collective 2832 2833 Input Parameters: 2834 + mat - the matrix 2835 . v1 - the vector to be multiplied by the Hermitian transpose 2836 - v2 - the vector to be added to the result 2837 2838 Output Parameter: 2839 . v3 - the result 2840 2841 Level: beginner 2842 2843 Note: 2844 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2845 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2846 2847 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2848 @*/ 2849 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2850 { 2851 PetscFunctionBegin; 2852 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2853 PetscValidType(mat, 1); 2854 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2855 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2856 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2857 2858 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2859 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2860 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2861 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2862 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2863 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2864 MatCheckPreallocated(mat, 1); 2865 2866 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2867 PetscCall(VecLockReadPush(v1)); 2868 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2869 else { 2870 Vec w, z; 2871 PetscCall(VecDuplicate(v1, &w)); 2872 PetscCall(VecCopy(v1, w)); 2873 PetscCall(VecConjugate(w)); 2874 PetscCall(VecDuplicate(v3, &z)); 2875 PetscCall(MatMultTranspose(mat, w, z)); 2876 PetscCall(VecDestroy(&w)); 2877 PetscCall(VecConjugate(z)); 2878 if (v2 != v3) { 2879 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2880 } else { 2881 PetscCall(VecAXPY(v3, 1.0, z)); 2882 } 2883 PetscCall(VecDestroy(&z)); 2884 } 2885 PetscCall(VecLockReadPop(v1)); 2886 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2887 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2888 PetscFunctionReturn(PETSC_SUCCESS); 2889 } 2890 2891 /*@C 2892 MatGetFactorType - gets the type of factorization a matrix is 2893 2894 Not Collective 2895 2896 Input Parameter: 2897 . mat - the matrix 2898 2899 Output Parameter: 2900 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2901 2902 Level: intermediate 2903 2904 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2905 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2906 @*/ 2907 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2908 { 2909 PetscFunctionBegin; 2910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2911 PetscValidType(mat, 1); 2912 PetscAssertPointer(t, 2); 2913 *t = mat->factortype; 2914 PetscFunctionReturn(PETSC_SUCCESS); 2915 } 2916 2917 /*@C 2918 MatSetFactorType - sets the type of factorization a matrix is 2919 2920 Logically Collective 2921 2922 Input Parameters: 2923 + mat - the matrix 2924 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2925 2926 Level: intermediate 2927 2928 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2929 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2930 @*/ 2931 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2932 { 2933 PetscFunctionBegin; 2934 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2935 PetscValidType(mat, 1); 2936 mat->factortype = t; 2937 PetscFunctionReturn(PETSC_SUCCESS); 2938 } 2939 2940 /*@C 2941 MatGetInfo - Returns information about matrix storage (number of 2942 nonzeros, memory, etc.). 2943 2944 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2945 2946 Input Parameters: 2947 + mat - the matrix 2948 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2949 2950 Output Parameter: 2951 . info - matrix information context 2952 2953 Options Database Key: 2954 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2955 2956 Notes: 2957 The `MatInfo` context contains a variety of matrix data, including 2958 number of nonzeros allocated and used, number of mallocs during 2959 matrix assembly, etc. Additional information for factored matrices 2960 is provided (such as the fill ratio, number of mallocs during 2961 factorization, etc.). 2962 2963 Example: 2964 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2965 data within the MatInfo context. For example, 2966 .vb 2967 MatInfo info; 2968 Mat A; 2969 double mal, nz_a, nz_u; 2970 2971 MatGetInfo(A, MAT_LOCAL, &info); 2972 mal = info.mallocs; 2973 nz_a = info.nz_allocated; 2974 .ve 2975 2976 Fortran users should declare info as a double precision 2977 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2978 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2979 a complete list of parameter names. 2980 .vb 2981 double precision info(MAT_INFO_SIZE) 2982 double precision mal, nz_a 2983 Mat A 2984 integer ierr 2985 2986 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2987 mal = info(MAT_INFO_MALLOCS) 2988 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2989 .ve 2990 2991 Level: intermediate 2992 2993 Developer Note: 2994 The Fortran interface is not autogenerated as the 2995 interface definition cannot be generated correctly [due to `MatInfo` argument] 2996 2997 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2998 @*/ 2999 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3000 { 3001 PetscFunctionBegin; 3002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3003 PetscValidType(mat, 1); 3004 PetscAssertPointer(info, 3); 3005 MatCheckPreallocated(mat, 1); 3006 PetscUseTypeMethod(mat, getinfo, flag, info); 3007 PetscFunctionReturn(PETSC_SUCCESS); 3008 } 3009 3010 /* 3011 This is used by external packages where it is not easy to get the info from the actual 3012 matrix factorization. 3013 */ 3014 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3015 { 3016 PetscFunctionBegin; 3017 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3018 PetscFunctionReturn(PETSC_SUCCESS); 3019 } 3020 3021 /*@C 3022 MatLUFactor - Performs in-place LU factorization of matrix. 3023 3024 Collective 3025 3026 Input Parameters: 3027 + mat - the matrix 3028 . row - row permutation 3029 . col - column permutation 3030 - info - options for factorization, includes 3031 .vb 3032 fill - expected fill as ratio of original fill. 3033 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3034 Run with the option -info to determine an optimal value to use 3035 .ve 3036 3037 Level: developer 3038 3039 Notes: 3040 Most users should employ the `KSP` interface for linear solvers 3041 instead of working directly with matrix algebra routines such as this. 3042 See, e.g., `KSPCreate()`. 3043 3044 This changes the state of the matrix to a factored matrix; it cannot be used 3045 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3046 3047 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3048 when not using `KSP`. 3049 3050 Developer Note: 3051 The Fortran interface is not autogenerated as the 3052 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3053 3054 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3055 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3056 @*/ 3057 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3058 { 3059 MatFactorInfo tinfo; 3060 3061 PetscFunctionBegin; 3062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3063 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3064 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3065 if (info) PetscAssertPointer(info, 4); 3066 PetscValidType(mat, 1); 3067 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3068 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3069 MatCheckPreallocated(mat, 1); 3070 if (!info) { 3071 PetscCall(MatFactorInfoInitialize(&tinfo)); 3072 info = &tinfo; 3073 } 3074 3075 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3076 PetscUseTypeMethod(mat, lufactor, row, col, info); 3077 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3078 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3079 PetscFunctionReturn(PETSC_SUCCESS); 3080 } 3081 3082 /*@C 3083 MatILUFactor - Performs in-place ILU factorization of matrix. 3084 3085 Collective 3086 3087 Input Parameters: 3088 + mat - the matrix 3089 . row - row permutation 3090 . col - column permutation 3091 - info - structure containing 3092 .vb 3093 levels - number of levels of fill. 3094 expected fill - as ratio of original fill. 3095 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3096 missing diagonal entries) 3097 .ve 3098 3099 Level: developer 3100 3101 Notes: 3102 Most users should employ the `KSP` interface for linear solvers 3103 instead of working directly with matrix algebra routines such as this. 3104 See, e.g., `KSPCreate()`. 3105 3106 Probably really in-place only when level of fill is zero, otherwise allocates 3107 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3108 when not using `KSP`. 3109 3110 Developer Note: 3111 The Fortran interface is not autogenerated as the 3112 interface definition cannot be generated correctly [due to MatFactorInfo] 3113 3114 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3115 @*/ 3116 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3117 { 3118 PetscFunctionBegin; 3119 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3120 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3121 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3122 PetscAssertPointer(info, 4); 3123 PetscValidType(mat, 1); 3124 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3125 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3126 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3127 MatCheckPreallocated(mat, 1); 3128 3129 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3130 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3131 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3132 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3133 PetscFunctionReturn(PETSC_SUCCESS); 3134 } 3135 3136 /*@C 3137 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3138 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3139 3140 Collective 3141 3142 Input Parameters: 3143 + fact - the factor matrix obtained with `MatGetFactor()` 3144 . mat - the matrix 3145 . row - the row permutation 3146 . col - the column permutation 3147 - info - options for factorization, includes 3148 .vb 3149 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3150 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3151 .ve 3152 3153 Level: developer 3154 3155 Notes: 3156 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3157 3158 Most users should employ the simplified `KSP` interface for linear solvers 3159 instead of working directly with matrix algebra routines such as this. 3160 See, e.g., `KSPCreate()`. 3161 3162 Developer Note: 3163 The Fortran interface is not autogenerated as the 3164 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3165 3166 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3167 @*/ 3168 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3169 { 3170 MatFactorInfo tinfo; 3171 3172 PetscFunctionBegin; 3173 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3174 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3175 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3176 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3177 if (info) PetscAssertPointer(info, 5); 3178 PetscValidType(fact, 1); 3179 PetscValidType(mat, 2); 3180 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3181 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3182 MatCheckPreallocated(mat, 2); 3183 if (!info) { 3184 PetscCall(MatFactorInfoInitialize(&tinfo)); 3185 info = &tinfo; 3186 } 3187 3188 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3189 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3190 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3191 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3192 PetscFunctionReturn(PETSC_SUCCESS); 3193 } 3194 3195 /*@C 3196 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3197 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3198 3199 Collective 3200 3201 Input Parameters: 3202 + fact - the factor matrix obtained with `MatGetFactor()` 3203 . mat - the matrix 3204 - info - options for factorization 3205 3206 Level: developer 3207 3208 Notes: 3209 See `MatLUFactor()` for in-place factorization. See 3210 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3211 3212 Most users should employ the `KSP` interface for linear solvers 3213 instead of working directly with matrix algebra routines such as this. 3214 See, e.g., `KSPCreate()`. 3215 3216 Developer Note: 3217 The Fortran interface is not autogenerated as the 3218 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3219 3220 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3221 @*/ 3222 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3223 { 3224 MatFactorInfo tinfo; 3225 3226 PetscFunctionBegin; 3227 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3228 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3229 PetscValidType(fact, 1); 3230 PetscValidType(mat, 2); 3231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3232 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3233 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3234 3235 MatCheckPreallocated(mat, 2); 3236 if (!info) { 3237 PetscCall(MatFactorInfoInitialize(&tinfo)); 3238 info = &tinfo; 3239 } 3240 3241 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3242 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3243 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3244 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3245 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3246 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3247 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3248 PetscFunctionReturn(PETSC_SUCCESS); 3249 } 3250 3251 /*@C 3252 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3253 symmetric matrix. 3254 3255 Collective 3256 3257 Input Parameters: 3258 + mat - the matrix 3259 . perm - row and column permutations 3260 - info - expected fill as ratio of original fill 3261 3262 Level: developer 3263 3264 Notes: 3265 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3266 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3267 3268 Most users should employ the `KSP` interface for linear solvers 3269 instead of working directly with matrix algebra routines such as this. 3270 See, e.g., `KSPCreate()`. 3271 3272 Developer Note: 3273 The Fortran interface is not autogenerated as the 3274 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3275 3276 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3277 `MatGetOrdering()` 3278 @*/ 3279 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3280 { 3281 MatFactorInfo tinfo; 3282 3283 PetscFunctionBegin; 3284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3285 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3286 if (info) PetscAssertPointer(info, 3); 3287 PetscValidType(mat, 1); 3288 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3289 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3290 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3291 MatCheckPreallocated(mat, 1); 3292 if (!info) { 3293 PetscCall(MatFactorInfoInitialize(&tinfo)); 3294 info = &tinfo; 3295 } 3296 3297 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3298 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3299 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3300 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3301 PetscFunctionReturn(PETSC_SUCCESS); 3302 } 3303 3304 /*@C 3305 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3306 of a symmetric matrix. 3307 3308 Collective 3309 3310 Input Parameters: 3311 + fact - the factor matrix obtained with `MatGetFactor()` 3312 . mat - the matrix 3313 . perm - row and column permutations 3314 - info - options for factorization, includes 3315 .vb 3316 fill - expected fill as ratio of original fill. 3317 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3318 Run with the option -info to determine an optimal value to use 3319 .ve 3320 3321 Level: developer 3322 3323 Notes: 3324 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3325 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3326 3327 Most users should employ the `KSP` interface for linear solvers 3328 instead of working directly with matrix algebra routines such as this. 3329 See, e.g., `KSPCreate()`. 3330 3331 Developer Note: 3332 The Fortran interface is not autogenerated as the 3333 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3334 3335 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3336 `MatGetOrdering()` 3337 @*/ 3338 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3339 { 3340 MatFactorInfo tinfo; 3341 3342 PetscFunctionBegin; 3343 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3344 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3345 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3346 if (info) PetscAssertPointer(info, 4); 3347 PetscValidType(fact, 1); 3348 PetscValidType(mat, 2); 3349 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3350 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3351 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3352 MatCheckPreallocated(mat, 2); 3353 if (!info) { 3354 PetscCall(MatFactorInfoInitialize(&tinfo)); 3355 info = &tinfo; 3356 } 3357 3358 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3359 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3360 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3361 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3362 PetscFunctionReturn(PETSC_SUCCESS); 3363 } 3364 3365 /*@C 3366 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3367 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3368 `MatCholeskyFactorSymbolic()`. 3369 3370 Collective 3371 3372 Input Parameters: 3373 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3374 . mat - the initial matrix that is to be factored 3375 - info - options for factorization 3376 3377 Level: developer 3378 3379 Note: 3380 Most users should employ the `KSP` interface for linear solvers 3381 instead of working directly with matrix algebra routines such as this. 3382 See, e.g., `KSPCreate()`. 3383 3384 Developer Note: 3385 The Fortran interface is not autogenerated as the 3386 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3387 3388 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3389 @*/ 3390 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3391 { 3392 MatFactorInfo tinfo; 3393 3394 PetscFunctionBegin; 3395 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3397 PetscValidType(fact, 1); 3398 PetscValidType(mat, 2); 3399 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3400 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3401 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3402 MatCheckPreallocated(mat, 2); 3403 if (!info) { 3404 PetscCall(MatFactorInfoInitialize(&tinfo)); 3405 info = &tinfo; 3406 } 3407 3408 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3409 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3410 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3411 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3412 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3413 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3414 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3415 PetscFunctionReturn(PETSC_SUCCESS); 3416 } 3417 3418 /*@ 3419 MatQRFactor - Performs in-place QR factorization of matrix. 3420 3421 Collective 3422 3423 Input Parameters: 3424 + mat - the matrix 3425 . col - column permutation 3426 - info - options for factorization, includes 3427 .vb 3428 fill - expected fill as ratio of original fill. 3429 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3430 Run with the option -info to determine an optimal value to use 3431 .ve 3432 3433 Level: developer 3434 3435 Notes: 3436 Most users should employ the `KSP` interface for linear solvers 3437 instead of working directly with matrix algebra routines such as this. 3438 See, e.g., `KSPCreate()`. 3439 3440 This changes the state of the matrix to a factored matrix; it cannot be used 3441 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3442 3443 Developer Note: 3444 The Fortran interface is not autogenerated as the 3445 interface definition cannot be generated correctly [due to MatFactorInfo] 3446 3447 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3448 `MatSetUnfactored()` 3449 @*/ 3450 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3451 { 3452 PetscFunctionBegin; 3453 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3454 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3455 if (info) PetscAssertPointer(info, 3); 3456 PetscValidType(mat, 1); 3457 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3458 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3459 MatCheckPreallocated(mat, 1); 3460 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3461 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3462 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3463 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3464 PetscFunctionReturn(PETSC_SUCCESS); 3465 } 3466 3467 /*@ 3468 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3469 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3470 3471 Collective 3472 3473 Input Parameters: 3474 + fact - the factor matrix obtained with `MatGetFactor()` 3475 . mat - the matrix 3476 . col - column permutation 3477 - info - options for factorization, includes 3478 .vb 3479 fill - expected fill as ratio of original fill. 3480 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3481 Run with the option -info to determine an optimal value to use 3482 .ve 3483 3484 Level: developer 3485 3486 Note: 3487 Most users should employ the `KSP` interface for linear solvers 3488 instead of working directly with matrix algebra routines such as this. 3489 See, e.g., `KSPCreate()`. 3490 3491 Developer Note: 3492 The Fortran interface is not autogenerated as the 3493 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3494 3495 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3496 @*/ 3497 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3498 { 3499 MatFactorInfo tinfo; 3500 3501 PetscFunctionBegin; 3502 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3503 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3504 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3505 if (info) PetscAssertPointer(info, 4); 3506 PetscValidType(fact, 1); 3507 PetscValidType(mat, 2); 3508 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3509 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3510 MatCheckPreallocated(mat, 2); 3511 if (!info) { 3512 PetscCall(MatFactorInfoInitialize(&tinfo)); 3513 info = &tinfo; 3514 } 3515 3516 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3517 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3518 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3519 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3520 PetscFunctionReturn(PETSC_SUCCESS); 3521 } 3522 3523 /*@ 3524 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3525 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3526 3527 Collective 3528 3529 Input Parameters: 3530 + fact - the factor matrix obtained with `MatGetFactor()` 3531 . mat - the matrix 3532 - info - options for factorization 3533 3534 Level: developer 3535 3536 Notes: 3537 See `MatQRFactor()` for in-place factorization. 3538 3539 Most users should employ the `KSP` interface for linear solvers 3540 instead of working directly with matrix algebra routines such as this. 3541 See, e.g., `KSPCreate()`. 3542 3543 Developer Note: 3544 The Fortran interface is not autogenerated as the 3545 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3546 3547 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3548 @*/ 3549 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3550 { 3551 MatFactorInfo tinfo; 3552 3553 PetscFunctionBegin; 3554 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3556 PetscValidType(fact, 1); 3557 PetscValidType(mat, 2); 3558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3559 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3560 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3561 3562 MatCheckPreallocated(mat, 2); 3563 if (!info) { 3564 PetscCall(MatFactorInfoInitialize(&tinfo)); 3565 info = &tinfo; 3566 } 3567 3568 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3569 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3570 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3571 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3572 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3573 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3574 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3575 PetscFunctionReturn(PETSC_SUCCESS); 3576 } 3577 3578 /*@ 3579 MatSolve - Solves $A x = b$, given a factored matrix. 3580 3581 Neighbor-wise Collective 3582 3583 Input Parameters: 3584 + mat - the factored matrix 3585 - b - the right-hand-side vector 3586 3587 Output Parameter: 3588 . x - the result vector 3589 3590 Level: developer 3591 3592 Notes: 3593 The vectors `b` and `x` cannot be the same. I.e., one cannot 3594 call `MatSolve`(A,x,x). 3595 3596 Most users should employ the `KSP` interface for linear solvers 3597 instead of working directly with matrix algebra routines such as this. 3598 See, e.g., `KSPCreate()`. 3599 3600 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3601 @*/ 3602 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3603 { 3604 PetscFunctionBegin; 3605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3606 PetscValidType(mat, 1); 3607 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3608 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3609 PetscCheckSameComm(mat, 1, b, 2); 3610 PetscCheckSameComm(mat, 1, x, 3); 3611 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3612 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3613 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3614 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3615 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3616 MatCheckPreallocated(mat, 1); 3617 3618 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3619 if (mat->factorerrortype) { 3620 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3621 PetscCall(VecSetInf(x)); 3622 } else PetscUseTypeMethod(mat, solve, b, x); 3623 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3624 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3625 PetscFunctionReturn(PETSC_SUCCESS); 3626 } 3627 3628 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3629 { 3630 Vec b, x; 3631 PetscInt N, i; 3632 PetscErrorCode (*f)(Mat, Vec, Vec); 3633 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3634 3635 PetscFunctionBegin; 3636 if (A->factorerrortype) { 3637 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3638 PetscCall(MatSetInf(X)); 3639 PetscFunctionReturn(PETSC_SUCCESS); 3640 } 3641 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3642 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3643 PetscCall(MatBoundToCPU(A, &Abound)); 3644 if (!Abound) { 3645 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3646 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3647 } 3648 #if PetscDefined(HAVE_CUDA) 3649 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3650 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3651 #elif PetscDefined(HAVE_HIP) 3652 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3653 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3654 #endif 3655 PetscCall(MatGetSize(B, NULL, &N)); 3656 for (i = 0; i < N; i++) { 3657 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3658 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3659 PetscCall((*f)(A, b, x)); 3660 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3661 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3662 } 3663 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3664 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3665 PetscFunctionReturn(PETSC_SUCCESS); 3666 } 3667 3668 /*@ 3669 MatMatSolve - Solves $A X = B$, given a factored matrix. 3670 3671 Neighbor-wise Collective 3672 3673 Input Parameters: 3674 + A - the factored matrix 3675 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3676 3677 Output Parameter: 3678 . X - the result matrix (dense matrix) 3679 3680 Level: developer 3681 3682 Note: 3683 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3684 otherwise, `B` and `X` cannot be the same. 3685 3686 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3687 @*/ 3688 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3689 { 3690 PetscFunctionBegin; 3691 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3692 PetscValidType(A, 1); 3693 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3694 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3695 PetscCheckSameComm(A, 1, B, 2); 3696 PetscCheckSameComm(A, 1, X, 3); 3697 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3698 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3699 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3700 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3701 MatCheckPreallocated(A, 1); 3702 3703 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3704 if (!A->ops->matsolve) { 3705 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3706 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3707 } else PetscUseTypeMethod(A, matsolve, B, X); 3708 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3709 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3710 PetscFunctionReturn(PETSC_SUCCESS); 3711 } 3712 3713 /*@ 3714 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3715 3716 Neighbor-wise Collective 3717 3718 Input Parameters: 3719 + A - the factored matrix 3720 - B - the right-hand-side matrix (`MATDENSE` matrix) 3721 3722 Output Parameter: 3723 . X - the result matrix (dense matrix) 3724 3725 Level: developer 3726 3727 Note: 3728 The matrices `B` and `X` cannot be the same. I.e., one cannot 3729 call `MatMatSolveTranspose`(A,X,X). 3730 3731 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3732 @*/ 3733 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3734 { 3735 PetscFunctionBegin; 3736 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3737 PetscValidType(A, 1); 3738 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3739 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3740 PetscCheckSameComm(A, 1, B, 2); 3741 PetscCheckSameComm(A, 1, X, 3); 3742 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3743 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3744 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3745 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3746 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3747 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3748 MatCheckPreallocated(A, 1); 3749 3750 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3751 if (!A->ops->matsolvetranspose) { 3752 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3753 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3754 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3755 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3756 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3757 PetscFunctionReturn(PETSC_SUCCESS); 3758 } 3759 3760 /*@ 3761 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3762 3763 Neighbor-wise Collective 3764 3765 Input Parameters: 3766 + A - the factored matrix 3767 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3768 3769 Output Parameter: 3770 . X - the result matrix (dense matrix) 3771 3772 Level: developer 3773 3774 Note: 3775 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create `Bt` in sparse compressed row 3776 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3777 3778 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3779 @*/ 3780 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3781 { 3782 PetscFunctionBegin; 3783 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3784 PetscValidType(A, 1); 3785 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3786 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3787 PetscCheckSameComm(A, 1, Bt, 2); 3788 PetscCheckSameComm(A, 1, X, 3); 3789 3790 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3791 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3792 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3793 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3794 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3795 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3796 MatCheckPreallocated(A, 1); 3797 3798 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3799 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3800 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3801 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3802 PetscFunctionReturn(PETSC_SUCCESS); 3803 } 3804 3805 /*@ 3806 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3807 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3808 3809 Neighbor-wise Collective 3810 3811 Input Parameters: 3812 + mat - the factored matrix 3813 - b - the right-hand-side vector 3814 3815 Output Parameter: 3816 . x - the result vector 3817 3818 Level: developer 3819 3820 Notes: 3821 `MatSolve()` should be used for most applications, as it performs 3822 a forward solve followed by a backward solve. 3823 3824 The vectors `b` and `x` cannot be the same, i.e., one cannot 3825 call `MatForwardSolve`(A,x,x). 3826 3827 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3828 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3829 `MatForwardSolve()` solves $U^T*D y = b$, and 3830 `MatBackwardSolve()` solves $U x = y$. 3831 Thus they do not provide a symmetric preconditioner. 3832 3833 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3834 @*/ 3835 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3836 { 3837 PetscFunctionBegin; 3838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3839 PetscValidType(mat, 1); 3840 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3841 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3842 PetscCheckSameComm(mat, 1, b, 2); 3843 PetscCheckSameComm(mat, 1, x, 3); 3844 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3845 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3846 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3847 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3848 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3849 MatCheckPreallocated(mat, 1); 3850 3851 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3852 PetscUseTypeMethod(mat, forwardsolve, b, x); 3853 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3854 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3855 PetscFunctionReturn(PETSC_SUCCESS); 3856 } 3857 3858 /*@ 3859 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3860 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3861 3862 Neighbor-wise Collective 3863 3864 Input Parameters: 3865 + mat - the factored matrix 3866 - b - the right-hand-side vector 3867 3868 Output Parameter: 3869 . x - the result vector 3870 3871 Level: developer 3872 3873 Notes: 3874 `MatSolve()` should be used for most applications, as it performs 3875 a forward solve followed by a backward solve. 3876 3877 The vectors `b` and `x` cannot be the same. I.e., one cannot 3878 call `MatBackwardSolve`(A,x,x). 3879 3880 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3881 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3882 `MatForwardSolve()` solves $U^T*D y = b$, and 3883 `MatBackwardSolve()` solves $U x = y$. 3884 Thus they do not provide a symmetric preconditioner. 3885 3886 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3887 @*/ 3888 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3889 { 3890 PetscFunctionBegin; 3891 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3892 PetscValidType(mat, 1); 3893 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3894 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3895 PetscCheckSameComm(mat, 1, b, 2); 3896 PetscCheckSameComm(mat, 1, x, 3); 3897 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3898 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3899 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3900 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3901 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3902 MatCheckPreallocated(mat, 1); 3903 3904 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3905 PetscUseTypeMethod(mat, backwardsolve, b, x); 3906 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3907 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3908 PetscFunctionReturn(PETSC_SUCCESS); 3909 } 3910 3911 /*@ 3912 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3913 3914 Neighbor-wise Collective 3915 3916 Input Parameters: 3917 + mat - the factored matrix 3918 . b - the right-hand-side vector 3919 - y - the vector to be added to 3920 3921 Output Parameter: 3922 . x - the result vector 3923 3924 Level: developer 3925 3926 Note: 3927 The vectors `b` and `x` cannot be the same. I.e., one cannot 3928 call `MatSolveAdd`(A,x,y,x). 3929 3930 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3931 @*/ 3932 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3933 { 3934 PetscScalar one = 1.0; 3935 Vec tmp; 3936 3937 PetscFunctionBegin; 3938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3939 PetscValidType(mat, 1); 3940 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3941 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3942 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3943 PetscCheckSameComm(mat, 1, b, 2); 3944 PetscCheckSameComm(mat, 1, y, 3); 3945 PetscCheckSameComm(mat, 1, x, 4); 3946 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3947 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3948 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3949 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 3950 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3951 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 3952 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3953 MatCheckPreallocated(mat, 1); 3954 3955 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3956 if (mat->factorerrortype) { 3957 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3958 PetscCall(VecSetInf(x)); 3959 } else if (mat->ops->solveadd) { 3960 PetscUseTypeMethod(mat, solveadd, b, y, x); 3961 } else { 3962 /* do the solve then the add manually */ 3963 if (x != y) { 3964 PetscCall(MatSolve(mat, b, x)); 3965 PetscCall(VecAXPY(x, one, y)); 3966 } else { 3967 PetscCall(VecDuplicate(x, &tmp)); 3968 PetscCall(VecCopy(x, tmp)); 3969 PetscCall(MatSolve(mat, b, x)); 3970 PetscCall(VecAXPY(x, one, tmp)); 3971 PetscCall(VecDestroy(&tmp)); 3972 } 3973 } 3974 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3975 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3976 PetscFunctionReturn(PETSC_SUCCESS); 3977 } 3978 3979 /*@ 3980 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 3981 3982 Neighbor-wise Collective 3983 3984 Input Parameters: 3985 + mat - the factored matrix 3986 - b - the right-hand-side vector 3987 3988 Output Parameter: 3989 . x - the result vector 3990 3991 Level: developer 3992 3993 Notes: 3994 The vectors `b` and `x` cannot be the same. I.e., one cannot 3995 call `MatSolveTranspose`(A,x,x). 3996 3997 Most users should employ the `KSP` interface for linear solvers 3998 instead of working directly with matrix algebra routines such as this. 3999 See, e.g., `KSPCreate()`. 4000 4001 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4002 @*/ 4003 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4004 { 4005 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4006 4007 PetscFunctionBegin; 4008 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4009 PetscValidType(mat, 1); 4010 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4011 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4012 PetscCheckSameComm(mat, 1, b, 2); 4013 PetscCheckSameComm(mat, 1, x, 3); 4014 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4015 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4016 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4017 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4018 MatCheckPreallocated(mat, 1); 4019 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4020 if (mat->factorerrortype) { 4021 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4022 PetscCall(VecSetInf(x)); 4023 } else { 4024 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4025 PetscCall((*f)(mat, b, x)); 4026 } 4027 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4028 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4029 PetscFunctionReturn(PETSC_SUCCESS); 4030 } 4031 4032 /*@ 4033 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4034 factored matrix. 4035 4036 Neighbor-wise Collective 4037 4038 Input Parameters: 4039 + mat - the factored matrix 4040 . b - the right-hand-side vector 4041 - y - the vector to be added to 4042 4043 Output Parameter: 4044 . x - the result vector 4045 4046 Level: developer 4047 4048 Note: 4049 The vectors `b` and `x` cannot be the same. I.e., one cannot 4050 call `MatSolveTransposeAdd`(A,x,y,x). 4051 4052 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4053 @*/ 4054 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4055 { 4056 PetscScalar one = 1.0; 4057 Vec tmp; 4058 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4059 4060 PetscFunctionBegin; 4061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4062 PetscValidType(mat, 1); 4063 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4064 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4065 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4066 PetscCheckSameComm(mat, 1, b, 2); 4067 PetscCheckSameComm(mat, 1, y, 3); 4068 PetscCheckSameComm(mat, 1, x, 4); 4069 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4070 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4071 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4072 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4073 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4074 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4075 MatCheckPreallocated(mat, 1); 4076 4077 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4078 if (mat->factorerrortype) { 4079 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4080 PetscCall(VecSetInf(x)); 4081 } else if (f) { 4082 PetscCall((*f)(mat, b, y, x)); 4083 } else { 4084 /* do the solve then the add manually */ 4085 if (x != y) { 4086 PetscCall(MatSolveTranspose(mat, b, x)); 4087 PetscCall(VecAXPY(x, one, y)); 4088 } else { 4089 PetscCall(VecDuplicate(x, &tmp)); 4090 PetscCall(VecCopy(x, tmp)); 4091 PetscCall(MatSolveTranspose(mat, b, x)); 4092 PetscCall(VecAXPY(x, one, tmp)); 4093 PetscCall(VecDestroy(&tmp)); 4094 } 4095 } 4096 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4097 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4098 PetscFunctionReturn(PETSC_SUCCESS); 4099 } 4100 4101 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4102 /*@ 4103 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4104 4105 Neighbor-wise Collective 4106 4107 Input Parameters: 4108 + mat - the matrix 4109 . b - the right hand side 4110 . omega - the relaxation factor 4111 . flag - flag indicating the type of SOR (see below) 4112 . shift - diagonal shift 4113 . its - the number of iterations 4114 - lits - the number of local iterations 4115 4116 Output Parameter: 4117 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4118 4119 SOR Flags: 4120 + `SOR_FORWARD_SWEEP` - forward SOR 4121 . `SOR_BACKWARD_SWEEP` - backward SOR 4122 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4123 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4124 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4125 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4126 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4127 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4128 upper/lower triangular part of matrix to 4129 vector (with omega) 4130 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4131 4132 Level: developer 4133 4134 Notes: 4135 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4136 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4137 on each processor. 4138 4139 Application programmers will not generally use `MatSOR()` directly, 4140 but instead will employ the `KSP`/`PC` interface. 4141 4142 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4143 4144 Most users should employ the `KSP` interface for linear solvers 4145 instead of working directly with matrix algebra routines such as this. 4146 See, e.g., `KSPCreate()`. 4147 4148 Vectors `x` and `b` CANNOT be the same 4149 4150 The flags are implemented as bitwise inclusive or operations. 4151 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4152 to specify a zero initial guess for SSOR. 4153 4154 Developer Note: 4155 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4156 4157 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4158 @*/ 4159 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4160 { 4161 PetscFunctionBegin; 4162 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4163 PetscValidType(mat, 1); 4164 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4165 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4166 PetscCheckSameComm(mat, 1, b, 2); 4167 PetscCheckSameComm(mat, 1, x, 8); 4168 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4169 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4170 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4171 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4172 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4173 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4174 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4175 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4176 4177 MatCheckPreallocated(mat, 1); 4178 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4179 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4180 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4181 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4182 PetscFunctionReturn(PETSC_SUCCESS); 4183 } 4184 4185 /* 4186 Default matrix copy routine. 4187 */ 4188 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4189 { 4190 PetscInt i, rstart = 0, rend = 0, nz; 4191 const PetscInt *cwork; 4192 const PetscScalar *vwork; 4193 4194 PetscFunctionBegin; 4195 if (B->assembled) PetscCall(MatZeroEntries(B)); 4196 if (str == SAME_NONZERO_PATTERN) { 4197 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4198 for (i = rstart; i < rend; i++) { 4199 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4200 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4201 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4202 } 4203 } else { 4204 PetscCall(MatAYPX(B, 0.0, A, str)); 4205 } 4206 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4207 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4208 PetscFunctionReturn(PETSC_SUCCESS); 4209 } 4210 4211 /*@ 4212 MatCopy - Copies a matrix to another matrix. 4213 4214 Collective 4215 4216 Input Parameters: 4217 + A - the matrix 4218 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4219 4220 Output Parameter: 4221 . B - where the copy is put 4222 4223 Level: intermediate 4224 4225 Notes: 4226 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4227 4228 `MatCopy()` copies the matrix entries of a matrix to another existing 4229 matrix (after first zeroing the second matrix). A related routine is 4230 `MatConvert()`, which first creates a new matrix and then copies the data. 4231 4232 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4233 @*/ 4234 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4235 { 4236 PetscInt i; 4237 4238 PetscFunctionBegin; 4239 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4240 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4241 PetscValidType(A, 1); 4242 PetscValidType(B, 2); 4243 PetscCheckSameComm(A, 1, B, 2); 4244 MatCheckPreallocated(B, 2); 4245 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4246 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4247 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4248 A->cmap->N, B->cmap->N); 4249 MatCheckPreallocated(A, 1); 4250 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4251 4252 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4253 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4254 else PetscCall(MatCopy_Basic(A, B, str)); 4255 4256 B->stencil.dim = A->stencil.dim; 4257 B->stencil.noc = A->stencil.noc; 4258 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4259 B->stencil.dims[i] = A->stencil.dims[i]; 4260 B->stencil.starts[i] = A->stencil.starts[i]; 4261 } 4262 4263 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4264 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4265 PetscFunctionReturn(PETSC_SUCCESS); 4266 } 4267 4268 /*@C 4269 MatConvert - Converts a matrix to another matrix, either of the same 4270 or different type. 4271 4272 Collective 4273 4274 Input Parameters: 4275 + mat - the matrix 4276 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4277 same type as the original matrix. 4278 - reuse - denotes if the destination matrix is to be created or reused. 4279 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use 4280 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused). 4281 4282 Output Parameter: 4283 . M - pointer to place new matrix 4284 4285 Level: intermediate 4286 4287 Notes: 4288 `MatConvert()` first creates a new matrix and then copies the data from 4289 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4290 entries of one matrix to another already existing matrix context. 4291 4292 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4293 the MPI communicator of the generated matrix is always the same as the communicator 4294 of the input matrix. 4295 4296 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4297 @*/ 4298 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4299 { 4300 PetscBool sametype, issame, flg; 4301 PetscBool3 issymmetric, ishermitian; 4302 char convname[256], mtype[256]; 4303 Mat B; 4304 4305 PetscFunctionBegin; 4306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4307 PetscValidType(mat, 1); 4308 PetscAssertPointer(M, 4); 4309 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4310 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4311 MatCheckPreallocated(mat, 1); 4312 4313 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4314 if (flg) newtype = mtype; 4315 4316 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4317 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4318 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4319 if (reuse == MAT_REUSE_MATRIX) { 4320 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4321 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4322 } 4323 4324 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4325 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4326 PetscFunctionReturn(PETSC_SUCCESS); 4327 } 4328 4329 /* Cache Mat options because some converters use MatHeaderReplace */ 4330 issymmetric = mat->symmetric; 4331 ishermitian = mat->hermitian; 4332 4333 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4334 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4335 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4336 } else { 4337 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4338 const char *prefix[3] = {"seq", "mpi", ""}; 4339 PetscInt i; 4340 /* 4341 Order of precedence: 4342 0) See if newtype is a superclass of the current matrix. 4343 1) See if a specialized converter is known to the current matrix. 4344 2) See if a specialized converter is known to the desired matrix class. 4345 3) See if a good general converter is registered for the desired class 4346 (as of 6/27/03 only MATMPIADJ falls into this category). 4347 4) See if a good general converter is known for the current matrix. 4348 5) Use a really basic converter. 4349 */ 4350 4351 /* 0) See if newtype is a superclass of the current matrix. 4352 i.e mat is mpiaij and newtype is aij */ 4353 for (i = 0; i < 2; i++) { 4354 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4355 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4356 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4357 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4358 if (flg) { 4359 if (reuse == MAT_INPLACE_MATRIX) { 4360 PetscCall(PetscInfo(mat, "Early return\n")); 4361 PetscFunctionReturn(PETSC_SUCCESS); 4362 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4363 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4364 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4365 PetscFunctionReturn(PETSC_SUCCESS); 4366 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4367 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4368 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4369 PetscFunctionReturn(PETSC_SUCCESS); 4370 } 4371 } 4372 } 4373 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4374 for (i = 0; i < 3; i++) { 4375 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4380 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4381 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4382 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4383 if (conv) goto foundconv; 4384 } 4385 4386 /* 2) See if a specialized converter is known to the desired matrix class. */ 4387 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4388 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4389 PetscCall(MatSetType(B, newtype)); 4390 for (i = 0; i < 3; i++) { 4391 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4392 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4394 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4395 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4396 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4397 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4398 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4399 if (conv) { 4400 PetscCall(MatDestroy(&B)); 4401 goto foundconv; 4402 } 4403 } 4404 4405 /* 3) See if a good general converter is registered for the desired class */ 4406 conv = B->ops->convertfrom; 4407 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4408 PetscCall(MatDestroy(&B)); 4409 if (conv) goto foundconv; 4410 4411 /* 4) See if a good general converter is known for the current matrix */ 4412 if (mat->ops->convert) conv = mat->ops->convert; 4413 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4414 if (conv) goto foundconv; 4415 4416 /* 5) Use a really basic converter. */ 4417 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4418 conv = MatConvert_Basic; 4419 4420 foundconv: 4421 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4422 PetscCall((*conv)(mat, newtype, reuse, M)); 4423 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4424 /* the block sizes must be same if the mappings are copied over */ 4425 (*M)->rmap->bs = mat->rmap->bs; 4426 (*M)->cmap->bs = mat->cmap->bs; 4427 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4428 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4429 (*M)->rmap->mapping = mat->rmap->mapping; 4430 (*M)->cmap->mapping = mat->cmap->mapping; 4431 } 4432 (*M)->stencil.dim = mat->stencil.dim; 4433 (*M)->stencil.noc = mat->stencil.noc; 4434 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4435 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4436 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4437 } 4438 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4439 } 4440 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4441 4442 /* Copy Mat options */ 4443 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4444 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4445 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4446 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4447 PetscFunctionReturn(PETSC_SUCCESS); 4448 } 4449 4450 /*@C 4451 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4452 4453 Not Collective 4454 4455 Input Parameter: 4456 . mat - the matrix, must be a factored matrix 4457 4458 Output Parameter: 4459 . type - the string name of the package (do not free this string) 4460 4461 Level: intermediate 4462 4463 Fortran Note: 4464 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4465 4466 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4467 @*/ 4468 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4469 { 4470 PetscErrorCode (*conv)(Mat, MatSolverType *); 4471 4472 PetscFunctionBegin; 4473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4474 PetscValidType(mat, 1); 4475 PetscAssertPointer(type, 2); 4476 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4477 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4478 if (conv) PetscCall((*conv)(mat, type)); 4479 else *type = MATSOLVERPETSC; 4480 PetscFunctionReturn(PETSC_SUCCESS); 4481 } 4482 4483 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4484 struct _MatSolverTypeForSpecifcType { 4485 MatType mtype; 4486 /* no entry for MAT_FACTOR_NONE */ 4487 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4488 MatSolverTypeForSpecifcType next; 4489 }; 4490 4491 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4492 struct _MatSolverTypeHolder { 4493 char *name; 4494 MatSolverTypeForSpecifcType handlers; 4495 MatSolverTypeHolder next; 4496 }; 4497 4498 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4499 4500 /*@C 4501 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4502 4503 Input Parameters: 4504 + package - name of the package, for example petsc or superlu 4505 . mtype - the matrix type that works with this package 4506 . ftype - the type of factorization supported by the package 4507 - createfactor - routine that will create the factored matrix ready to be used 4508 4509 Level: developer 4510 4511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `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 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 Level: developer 4573 4574 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4575 @*/ 4576 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4577 { 4578 MatSolverTypeHolder next = MatSolverTypeHolders; 4579 PetscBool flg; 4580 MatSolverTypeForSpecifcType inext; 4581 4582 PetscFunctionBegin; 4583 if (foundtype) *foundtype = PETSC_FALSE; 4584 if (foundmtype) *foundmtype = PETSC_FALSE; 4585 if (createfactor) *createfactor = NULL; 4586 4587 if (type) { 4588 while (next) { 4589 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4590 if (flg) { 4591 if (foundtype) *foundtype = PETSC_TRUE; 4592 inext = next->handlers; 4593 while (inext) { 4594 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4595 if (flg) { 4596 if (foundmtype) *foundmtype = PETSC_TRUE; 4597 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4598 PetscFunctionReturn(PETSC_SUCCESS); 4599 } 4600 inext = inext->next; 4601 } 4602 } 4603 next = next->next; 4604 } 4605 } else { 4606 while (next) { 4607 inext = next->handlers; 4608 while (inext) { 4609 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4610 if (flg && inext->createfactor[(int)ftype - 1]) { 4611 if (foundtype) *foundtype = PETSC_TRUE; 4612 if (foundmtype) *foundmtype = PETSC_TRUE; 4613 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4614 PetscFunctionReturn(PETSC_SUCCESS); 4615 } 4616 inext = inext->next; 4617 } 4618 next = next->next; 4619 } 4620 /* try with base classes inext->mtype */ 4621 next = MatSolverTypeHolders; 4622 while (next) { 4623 inext = next->handlers; 4624 while (inext) { 4625 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4626 if (flg && inext->createfactor[(int)ftype - 1]) { 4627 if (foundtype) *foundtype = PETSC_TRUE; 4628 if (foundmtype) *foundmtype = PETSC_TRUE; 4629 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4630 PetscFunctionReturn(PETSC_SUCCESS); 4631 } 4632 inext = inext->next; 4633 } 4634 next = next->next; 4635 } 4636 } 4637 PetscFunctionReturn(PETSC_SUCCESS); 4638 } 4639 4640 PetscErrorCode MatSolverTypeDestroy(void) 4641 { 4642 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4643 MatSolverTypeForSpecifcType inext, iprev; 4644 4645 PetscFunctionBegin; 4646 while (next) { 4647 PetscCall(PetscFree(next->name)); 4648 inext = next->handlers; 4649 while (inext) { 4650 PetscCall(PetscFree(inext->mtype)); 4651 iprev = inext; 4652 inext = inext->next; 4653 PetscCall(PetscFree(iprev)); 4654 } 4655 prev = next; 4656 next = next->next; 4657 PetscCall(PetscFree(prev)); 4658 } 4659 MatSolverTypeHolders = NULL; 4660 PetscFunctionReturn(PETSC_SUCCESS); 4661 } 4662 4663 /*@C 4664 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4665 4666 Logically Collective 4667 4668 Input Parameter: 4669 . mat - the matrix 4670 4671 Output Parameter: 4672 . flg - `PETSC_TRUE` if uses the ordering 4673 4674 Level: developer 4675 4676 Note: 4677 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4678 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4679 4680 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4681 @*/ 4682 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4683 { 4684 PetscFunctionBegin; 4685 *flg = mat->canuseordering; 4686 PetscFunctionReturn(PETSC_SUCCESS); 4687 } 4688 4689 /*@C 4690 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4691 4692 Logically Collective 4693 4694 Input Parameters: 4695 + mat - the matrix obtained with `MatGetFactor()` 4696 - ftype - the factorization type to be used 4697 4698 Output Parameter: 4699 . otype - the preferred ordering type 4700 4701 Level: developer 4702 4703 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4704 @*/ 4705 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4706 { 4707 PetscFunctionBegin; 4708 *otype = mat->preferredordering[ftype]; 4709 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4710 PetscFunctionReturn(PETSC_SUCCESS); 4711 } 4712 4713 /*@C 4714 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4715 4716 Collective 4717 4718 Input Parameters: 4719 + mat - the matrix 4720 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4721 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4722 4723 Output Parameter: 4724 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4725 4726 Options Database Key: 4727 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4728 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4729 4730 Level: intermediate 4731 4732 Notes: 4733 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4734 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4735 4736 Users usually access the factorization solvers via `KSP` 4737 4738 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4739 such as pastix, superlu, mumps etc. 4740 4741 PETSc must have been ./configure to use the external solver, using the option --download-package 4742 4743 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4744 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4745 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4746 4747 Developer Note: 4748 This should actually be called `MatCreateFactor()` since it creates a new factor object 4749 4750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4751 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4752 @*/ 4753 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4754 { 4755 PetscBool foundtype, foundmtype; 4756 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4760 PetscValidType(mat, 1); 4761 4762 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4763 MatCheckPreallocated(mat, 1); 4764 4765 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4766 if (!foundtype) { 4767 if (type) { 4768 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], 4769 ((PetscObject)mat)->type_name, type); 4770 } else { 4771 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); 4772 } 4773 } 4774 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4775 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); 4776 4777 PetscCall((*conv)(mat, ftype, f)); 4778 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4779 PetscFunctionReturn(PETSC_SUCCESS); 4780 } 4781 4782 /*@C 4783 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4784 4785 Not Collective 4786 4787 Input Parameters: 4788 + mat - the matrix 4789 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4790 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4791 4792 Output Parameter: 4793 . flg - PETSC_TRUE if the factorization is available 4794 4795 Level: intermediate 4796 4797 Notes: 4798 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4799 such as pastix, superlu, mumps etc. 4800 4801 PETSc must have been ./configure to use the external solver, using the option --download-package 4802 4803 Developer Note: 4804 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4805 4806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4807 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4808 @*/ 4809 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4810 { 4811 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4812 4813 PetscFunctionBegin; 4814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4815 PetscAssertPointer(flg, 4); 4816 4817 *flg = PETSC_FALSE; 4818 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4819 4820 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4821 MatCheckPreallocated(mat, 1); 4822 4823 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4824 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4825 PetscFunctionReturn(PETSC_SUCCESS); 4826 } 4827 4828 /*@ 4829 MatDuplicate - Duplicates a matrix including the non-zero structure. 4830 4831 Collective 4832 4833 Input Parameters: 4834 + mat - the matrix 4835 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4836 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4837 4838 Output Parameter: 4839 . M - pointer to place new matrix 4840 4841 Level: intermediate 4842 4843 Notes: 4844 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4845 4846 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4847 4848 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. 4849 4850 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4851 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4852 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4853 4854 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4855 @*/ 4856 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4857 { 4858 Mat B; 4859 VecType vtype; 4860 PetscInt i; 4861 PetscObject dm, container_h, container_d; 4862 void (*viewf)(void); 4863 4864 PetscFunctionBegin; 4865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4866 PetscValidType(mat, 1); 4867 PetscAssertPointer(M, 3); 4868 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4869 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4870 MatCheckPreallocated(mat, 1); 4871 4872 *M = NULL; 4873 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4874 PetscUseTypeMethod(mat, duplicate, op, M); 4875 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4876 B = *M; 4877 4878 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4879 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4880 PetscCall(MatGetVecType(mat, &vtype)); 4881 PetscCall(MatSetVecType(B, vtype)); 4882 4883 B->stencil.dim = mat->stencil.dim; 4884 B->stencil.noc = mat->stencil.noc; 4885 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4886 B->stencil.dims[i] = mat->stencil.dims[i]; 4887 B->stencil.starts[i] = mat->stencil.starts[i]; 4888 } 4889 4890 B->nooffproczerorows = mat->nooffproczerorows; 4891 B->nooffprocentries = mat->nooffprocentries; 4892 4893 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4894 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4895 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4896 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4897 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4898 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4899 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4900 PetscFunctionReturn(PETSC_SUCCESS); 4901 } 4902 4903 /*@ 4904 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4905 4906 Logically Collective 4907 4908 Input Parameter: 4909 . mat - the matrix 4910 4911 Output Parameter: 4912 . v - the diagonal of the matrix 4913 4914 Level: intermediate 4915 4916 Note: 4917 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4918 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4919 is larger than `ndiag`, the values of the remaining entries are unspecified. 4920 4921 Currently only correct in parallel for square matrices. 4922 4923 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4924 @*/ 4925 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4926 { 4927 PetscFunctionBegin; 4928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4929 PetscValidType(mat, 1); 4930 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4931 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4932 MatCheckPreallocated(mat, 1); 4933 if (PetscDefined(USE_DEBUG)) { 4934 PetscInt nv, row, col, ndiag; 4935 4936 PetscCall(VecGetLocalSize(v, &nv)); 4937 PetscCall(MatGetLocalSize(mat, &row, &col)); 4938 ndiag = PetscMin(row, col); 4939 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); 4940 } 4941 4942 PetscUseTypeMethod(mat, getdiagonal, v); 4943 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4944 PetscFunctionReturn(PETSC_SUCCESS); 4945 } 4946 4947 /*@C 4948 MatGetRowMin - Gets the minimum value (of the real part) of each 4949 row of the matrix 4950 4951 Logically Collective 4952 4953 Input Parameter: 4954 . mat - the matrix 4955 4956 Output Parameters: 4957 + v - the vector for storing the maximums 4958 - idx - the indices of the column found for each row (optional) 4959 4960 Level: intermediate 4961 4962 Note: 4963 The result of this call are the same as if one converted the matrix to dense format 4964 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4965 4966 This code is only implemented for a couple of matrix formats. 4967 4968 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4969 `MatGetRowMax()` 4970 @*/ 4971 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4972 { 4973 PetscFunctionBegin; 4974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4975 PetscValidType(mat, 1); 4976 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4977 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4978 4979 if (!mat->cmap->N) { 4980 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4981 if (idx) { 4982 PetscInt i, m = mat->rmap->n; 4983 for (i = 0; i < m; i++) idx[i] = -1; 4984 } 4985 } else { 4986 MatCheckPreallocated(mat, 1); 4987 } 4988 PetscUseTypeMethod(mat, getrowmin, v, idx); 4989 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4990 PetscFunctionReturn(PETSC_SUCCESS); 4991 } 4992 4993 /*@C 4994 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4995 row of the matrix 4996 4997 Logically Collective 4998 4999 Input Parameter: 5000 . mat - the matrix 5001 5002 Output Parameters: 5003 + v - the vector for storing the minimums 5004 - idx - the indices of the column found for each row (or `NULL` if not needed) 5005 5006 Level: intermediate 5007 5008 Notes: 5009 if a row is completely empty or has only 0.0 values then the `idx` value for that 5010 row is 0 (the first column). 5011 5012 This code is only implemented for a couple of matrix formats. 5013 5014 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5015 @*/ 5016 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5017 { 5018 PetscFunctionBegin; 5019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5020 PetscValidType(mat, 1); 5021 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5022 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5023 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5024 5025 if (!mat->cmap->N) { 5026 PetscCall(VecSet(v, 0.0)); 5027 if (idx) { 5028 PetscInt i, m = mat->rmap->n; 5029 for (i = 0; i < m; i++) idx[i] = -1; 5030 } 5031 } else { 5032 MatCheckPreallocated(mat, 1); 5033 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5034 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5035 } 5036 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5037 PetscFunctionReturn(PETSC_SUCCESS); 5038 } 5039 5040 /*@C 5041 MatGetRowMax - Gets the maximum value (of the real part) of each 5042 row of the matrix 5043 5044 Logically Collective 5045 5046 Input Parameter: 5047 . mat - the matrix 5048 5049 Output Parameters: 5050 + v - the vector for storing the maximums 5051 - idx - the indices of the column found for each row (optional) 5052 5053 Level: intermediate 5054 5055 Notes: 5056 The result of this call are the same as if one converted the matrix to dense format 5057 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5058 5059 This code is only implemented for a couple of matrix formats. 5060 5061 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5062 @*/ 5063 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5064 { 5065 PetscFunctionBegin; 5066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5067 PetscValidType(mat, 1); 5068 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5069 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5070 5071 if (!mat->cmap->N) { 5072 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5073 if (idx) { 5074 PetscInt i, m = mat->rmap->n; 5075 for (i = 0; i < m; i++) idx[i] = -1; 5076 } 5077 } else { 5078 MatCheckPreallocated(mat, 1); 5079 PetscUseTypeMethod(mat, getrowmax, v, idx); 5080 } 5081 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5082 PetscFunctionReturn(PETSC_SUCCESS); 5083 } 5084 5085 /*@C 5086 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5087 row of the matrix 5088 5089 Logically Collective 5090 5091 Input Parameter: 5092 . mat - the matrix 5093 5094 Output Parameters: 5095 + v - the vector for storing the maximums 5096 - idx - the indices of the column found for each row (or `NULL` if not needed) 5097 5098 Level: intermediate 5099 5100 Notes: 5101 if a row is completely empty or has only 0.0 values then the `idx` value for that 5102 row is 0 (the first column). 5103 5104 This code is only implemented for a couple of matrix formats. 5105 5106 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5107 @*/ 5108 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5109 { 5110 PetscFunctionBegin; 5111 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5112 PetscValidType(mat, 1); 5113 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5114 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5115 5116 if (!mat->cmap->N) { 5117 PetscCall(VecSet(v, 0.0)); 5118 if (idx) { 5119 PetscInt i, m = mat->rmap->n; 5120 for (i = 0; i < m; i++) idx[i] = -1; 5121 } 5122 } else { 5123 MatCheckPreallocated(mat, 1); 5124 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5125 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5126 } 5127 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5128 PetscFunctionReturn(PETSC_SUCCESS); 5129 } 5130 5131 /*@ 5132 MatGetRowSum - Gets the sum of each row of the matrix 5133 5134 Logically or Neighborhood Collective 5135 5136 Input Parameter: 5137 . mat - the matrix 5138 5139 Output Parameter: 5140 . v - the vector for storing the sum of rows 5141 5142 Level: intermediate 5143 5144 Note: 5145 This code is slow since it is not currently specialized for different formats 5146 5147 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5148 @*/ 5149 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5150 { 5151 Vec ones; 5152 5153 PetscFunctionBegin; 5154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5155 PetscValidType(mat, 1); 5156 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5157 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5158 MatCheckPreallocated(mat, 1); 5159 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5160 PetscCall(VecSet(ones, 1.)); 5161 PetscCall(MatMult(mat, ones, v)); 5162 PetscCall(VecDestroy(&ones)); 5163 PetscFunctionReturn(PETSC_SUCCESS); 5164 } 5165 5166 /*@ 5167 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5168 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5169 5170 Collective 5171 5172 Input Parameter: 5173 . mat - the matrix to provide the transpose 5174 5175 Output Parameter: 5176 . 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 5177 5178 Level: advanced 5179 5180 Note: 5181 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 5182 routine allows bypassing that call. 5183 5184 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5185 @*/ 5186 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5187 { 5188 PetscContainer rB = NULL; 5189 MatParentState *rb = NULL; 5190 5191 PetscFunctionBegin; 5192 PetscCall(PetscNew(&rb)); 5193 rb->id = ((PetscObject)mat)->id; 5194 rb->state = 0; 5195 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5196 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5197 PetscCall(PetscContainerSetPointer(rB, rb)); 5198 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5199 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5200 PetscCall(PetscObjectDereference((PetscObject)rB)); 5201 PetscFunctionReturn(PETSC_SUCCESS); 5202 } 5203 5204 /*@ 5205 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5206 5207 Collective 5208 5209 Input Parameters: 5210 + mat - the matrix to transpose 5211 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5212 5213 Output Parameter: 5214 . B - the transpose 5215 5216 Level: intermediate 5217 5218 Notes: 5219 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5220 5221 `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 5222 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5223 5224 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. 5225 5226 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5227 5228 If mat is unchanged from the last call this function returns immediately without recomputing the result 5229 5230 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5231 5232 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5233 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5234 @*/ 5235 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5236 { 5237 PetscContainer rB = NULL; 5238 MatParentState *rb = NULL; 5239 5240 PetscFunctionBegin; 5241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5242 PetscValidType(mat, 1); 5243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5244 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5245 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5246 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5247 MatCheckPreallocated(mat, 1); 5248 if (reuse == MAT_REUSE_MATRIX) { 5249 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5250 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5251 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5252 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5253 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5254 } 5255 5256 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5257 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5258 PetscUseTypeMethod(mat, transpose, reuse, B); 5259 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5260 } 5261 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5262 5263 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5264 if (reuse != MAT_INPLACE_MATRIX) { 5265 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5266 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5267 rb->state = ((PetscObject)mat)->state; 5268 rb->nonzerostate = mat->nonzerostate; 5269 } 5270 PetscFunctionReturn(PETSC_SUCCESS); 5271 } 5272 5273 /*@ 5274 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5275 5276 Collective 5277 5278 Input Parameter: 5279 . A - the matrix to transpose 5280 5281 Output Parameter: 5282 . 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 5283 numerical portion. 5284 5285 Level: intermediate 5286 5287 Note: 5288 This is not supported for many matrix types, use `MatTranspose()` in those cases 5289 5290 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5291 @*/ 5292 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5293 { 5294 PetscFunctionBegin; 5295 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5296 PetscValidType(A, 1); 5297 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5298 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5299 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5300 PetscUseTypeMethod(A, transposesymbolic, B); 5301 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5302 5303 PetscCall(MatTransposeSetPrecursor(A, *B)); 5304 PetscFunctionReturn(PETSC_SUCCESS); 5305 } 5306 5307 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5308 { 5309 PetscContainer rB; 5310 MatParentState *rb; 5311 5312 PetscFunctionBegin; 5313 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5314 PetscValidType(A, 1); 5315 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5316 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5317 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5318 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5319 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5320 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5321 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5322 PetscFunctionReturn(PETSC_SUCCESS); 5323 } 5324 5325 /*@ 5326 MatIsTranspose - Test whether a matrix is another one's transpose, 5327 or its own, in which case it tests symmetry. 5328 5329 Collective 5330 5331 Input Parameters: 5332 + A - the matrix to test 5333 . B - the matrix to test against, this can equal the first parameter 5334 - tol - tolerance, differences between entries smaller than this are counted as zero 5335 5336 Output Parameter: 5337 . flg - the result 5338 5339 Level: intermediate 5340 5341 Notes: 5342 Only available for `MATAIJ` matrices. 5343 5344 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5345 test involves parallel copies of the block off-diagonal parts of the matrix. 5346 5347 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5348 @*/ 5349 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5350 { 5351 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5352 5353 PetscFunctionBegin; 5354 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5355 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5356 PetscAssertPointer(flg, 4); 5357 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5358 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5359 *flg = PETSC_FALSE; 5360 if (f && g) { 5361 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5362 PetscCall((*f)(A, B, tol, flg)); 5363 } else { 5364 MatType mattype; 5365 5366 PetscCall(MatGetType(f ? B : A, &mattype)); 5367 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5368 } 5369 PetscFunctionReturn(PETSC_SUCCESS); 5370 } 5371 5372 /*@ 5373 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5374 5375 Collective 5376 5377 Input Parameters: 5378 + mat - the matrix to transpose and complex conjugate 5379 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5380 5381 Output Parameter: 5382 . B - the Hermitian transpose 5383 5384 Level: intermediate 5385 5386 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5387 @*/ 5388 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5389 { 5390 PetscFunctionBegin; 5391 PetscCall(MatTranspose(mat, reuse, B)); 5392 #if defined(PETSC_USE_COMPLEX) 5393 PetscCall(MatConjugate(*B)); 5394 #endif 5395 PetscFunctionReturn(PETSC_SUCCESS); 5396 } 5397 5398 /*@ 5399 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5400 5401 Collective 5402 5403 Input Parameters: 5404 + A - the matrix to test 5405 . B - the matrix to test against, this can equal the first parameter 5406 - tol - tolerance, differences between entries smaller than this are counted as zero 5407 5408 Output Parameter: 5409 . flg - the result 5410 5411 Level: intermediate 5412 5413 Notes: 5414 Only available for `MATAIJ` matrices. 5415 5416 The sequential algorithm 5417 has a running time of the order of the number of nonzeros; the parallel 5418 test involves parallel copies of the block off-diagonal parts of the matrix. 5419 5420 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5421 @*/ 5422 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5423 { 5424 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5425 5426 PetscFunctionBegin; 5427 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5428 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5429 PetscAssertPointer(flg, 4); 5430 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5431 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5432 if (f && g) { 5433 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5434 PetscCall((*f)(A, B, tol, flg)); 5435 } 5436 PetscFunctionReturn(PETSC_SUCCESS); 5437 } 5438 5439 /*@ 5440 MatPermute - Creates a new matrix with rows and columns permuted from the 5441 original. 5442 5443 Collective 5444 5445 Input Parameters: 5446 + mat - the matrix to permute 5447 . row - row permutation, each processor supplies only the permutation for its rows 5448 - col - column permutation, each processor supplies only the permutation for its columns 5449 5450 Output Parameter: 5451 . B - the permuted matrix 5452 5453 Level: advanced 5454 5455 Note: 5456 The index sets map from row/col of permuted matrix to row/col of original matrix. 5457 The index sets should be on the same communicator as mat and have the same local sizes. 5458 5459 Developer Note: 5460 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5461 exploit the fact that row and col are permutations, consider implementing the 5462 more general `MatCreateSubMatrix()` instead. 5463 5464 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5465 @*/ 5466 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5467 { 5468 PetscFunctionBegin; 5469 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5470 PetscValidType(mat, 1); 5471 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5472 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5473 PetscAssertPointer(B, 4); 5474 PetscCheckSameComm(mat, 1, row, 2); 5475 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5476 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5477 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5478 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5479 MatCheckPreallocated(mat, 1); 5480 5481 if (mat->ops->permute) { 5482 PetscUseTypeMethod(mat, permute, row, col, B); 5483 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5484 } else { 5485 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5486 } 5487 PetscFunctionReturn(PETSC_SUCCESS); 5488 } 5489 5490 /*@ 5491 MatEqual - Compares two matrices. 5492 5493 Collective 5494 5495 Input Parameters: 5496 + A - the first matrix 5497 - B - the second matrix 5498 5499 Output Parameter: 5500 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5501 5502 Level: intermediate 5503 5504 .seealso: [](ch_matrices), `Mat` 5505 @*/ 5506 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5507 { 5508 PetscFunctionBegin; 5509 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5510 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5511 PetscValidType(A, 1); 5512 PetscValidType(B, 2); 5513 PetscAssertPointer(flg, 3); 5514 PetscCheckSameComm(A, 1, B, 2); 5515 MatCheckPreallocated(A, 1); 5516 MatCheckPreallocated(B, 2); 5517 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5518 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5519 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, 5520 B->cmap->N); 5521 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5522 PetscUseTypeMethod(A, equal, B, flg); 5523 } else { 5524 PetscCall(MatMultEqual(A, B, 10, flg)); 5525 } 5526 PetscFunctionReturn(PETSC_SUCCESS); 5527 } 5528 5529 /*@ 5530 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5531 matrices that are stored as vectors. Either of the two scaling 5532 matrices can be `NULL`. 5533 5534 Collective 5535 5536 Input Parameters: 5537 + mat - the matrix to be scaled 5538 . l - the left scaling vector (or `NULL`) 5539 - r - the right scaling vector (or `NULL`) 5540 5541 Level: intermediate 5542 5543 Note: 5544 `MatDiagonalScale()` computes $A = LAR$, where 5545 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5546 The L scales the rows of the matrix, the R scales the columns of the matrix. 5547 5548 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5549 @*/ 5550 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5551 { 5552 PetscFunctionBegin; 5553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5554 PetscValidType(mat, 1); 5555 if (l) { 5556 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5557 PetscCheckSameComm(mat, 1, l, 2); 5558 } 5559 if (r) { 5560 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5561 PetscCheckSameComm(mat, 1, r, 3); 5562 } 5563 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5564 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5565 MatCheckPreallocated(mat, 1); 5566 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5567 5568 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5569 PetscUseTypeMethod(mat, diagonalscale, l, r); 5570 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5571 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5572 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5573 PetscFunctionReturn(PETSC_SUCCESS); 5574 } 5575 5576 /*@ 5577 MatScale - Scales all elements of a matrix by a given number. 5578 5579 Logically Collective 5580 5581 Input Parameters: 5582 + mat - the matrix to be scaled 5583 - a - the scaling value 5584 5585 Level: intermediate 5586 5587 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5588 @*/ 5589 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5590 { 5591 PetscFunctionBegin; 5592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5593 PetscValidType(mat, 1); 5594 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5595 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5596 PetscValidLogicalCollectiveScalar(mat, a, 2); 5597 MatCheckPreallocated(mat, 1); 5598 5599 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5600 if (a != (PetscScalar)1.0) { 5601 PetscUseTypeMethod(mat, scale, a); 5602 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5603 } 5604 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5605 PetscFunctionReturn(PETSC_SUCCESS); 5606 } 5607 5608 /*@ 5609 MatNorm - Calculates various norms of a matrix. 5610 5611 Collective 5612 5613 Input Parameters: 5614 + mat - the matrix 5615 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5616 5617 Output Parameter: 5618 . nrm - the resulting norm 5619 5620 Level: intermediate 5621 5622 .seealso: [](ch_matrices), `Mat` 5623 @*/ 5624 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5625 { 5626 PetscFunctionBegin; 5627 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5628 PetscValidType(mat, 1); 5629 PetscAssertPointer(nrm, 3); 5630 5631 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5632 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5633 MatCheckPreallocated(mat, 1); 5634 5635 PetscUseTypeMethod(mat, norm, type, nrm); 5636 PetscFunctionReturn(PETSC_SUCCESS); 5637 } 5638 5639 /* 5640 This variable is used to prevent counting of MatAssemblyBegin() that 5641 are called from within a MatAssemblyEnd(). 5642 */ 5643 static PetscInt MatAssemblyEnd_InUse = 0; 5644 /*@ 5645 MatAssemblyBegin - Begins assembling the matrix. This routine should 5646 be called after completing all calls to `MatSetValues()`. 5647 5648 Collective 5649 5650 Input Parameters: 5651 + mat - the matrix 5652 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5653 5654 Level: beginner 5655 5656 Notes: 5657 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5658 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5659 5660 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5661 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5662 using the matrix. 5663 5664 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5665 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 5666 a global collective operation requiring all processes that share the matrix. 5667 5668 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5669 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5670 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5671 5672 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5673 @*/ 5674 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5675 { 5676 PetscFunctionBegin; 5677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5678 PetscValidType(mat, 1); 5679 MatCheckPreallocated(mat, 1); 5680 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5681 if (mat->assembled) { 5682 mat->was_assembled = PETSC_TRUE; 5683 mat->assembled = PETSC_FALSE; 5684 } 5685 5686 if (!MatAssemblyEnd_InUse) { 5687 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5688 PetscTryTypeMethod(mat, assemblybegin, type); 5689 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5690 } else PetscTryTypeMethod(mat, assemblybegin, type); 5691 PetscFunctionReturn(PETSC_SUCCESS); 5692 } 5693 5694 /*@ 5695 MatAssembled - Indicates if a matrix has been assembled and is ready for 5696 use; for example, in matrix-vector product. 5697 5698 Not Collective 5699 5700 Input Parameter: 5701 . mat - the matrix 5702 5703 Output Parameter: 5704 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5705 5706 Level: advanced 5707 5708 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5709 @*/ 5710 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5711 { 5712 PetscFunctionBegin; 5713 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5714 PetscAssertPointer(assembled, 2); 5715 *assembled = mat->assembled; 5716 PetscFunctionReturn(PETSC_SUCCESS); 5717 } 5718 5719 /*@ 5720 MatAssemblyEnd - Completes assembling the matrix. This routine should 5721 be called after `MatAssemblyBegin()`. 5722 5723 Collective 5724 5725 Input Parameters: 5726 + mat - the matrix 5727 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5728 5729 Options Database Keys: 5730 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5731 . -mat_view ::ascii_info_detail - Prints more detailed info 5732 . -mat_view - Prints matrix in ASCII format 5733 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5734 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5735 . -display <name> - Sets display name (default is host) 5736 . -draw_pause <sec> - Sets number of seconds to pause after display 5737 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5738 . -viewer_socket_machine <machine> - Machine to use for socket 5739 . -viewer_socket_port <port> - Port number to use for socket 5740 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5741 5742 Level: beginner 5743 5744 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5745 @*/ 5746 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5747 { 5748 static PetscInt inassm = 0; 5749 PetscBool flg = PETSC_FALSE; 5750 5751 PetscFunctionBegin; 5752 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5753 PetscValidType(mat, 1); 5754 5755 inassm++; 5756 MatAssemblyEnd_InUse++; 5757 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5758 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5759 PetscTryTypeMethod(mat, assemblyend, type); 5760 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5761 } else PetscTryTypeMethod(mat, assemblyend, type); 5762 5763 /* Flush assembly is not a true assembly */ 5764 if (type != MAT_FLUSH_ASSEMBLY) { 5765 if (mat->num_ass) { 5766 if (!mat->symmetry_eternal) { 5767 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5768 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5769 } 5770 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5771 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5772 } 5773 mat->num_ass++; 5774 mat->assembled = PETSC_TRUE; 5775 mat->ass_nonzerostate = mat->nonzerostate; 5776 } 5777 5778 mat->insertmode = NOT_SET_VALUES; 5779 MatAssemblyEnd_InUse--; 5780 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5781 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5782 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5783 5784 if (mat->checksymmetryonassembly) { 5785 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5786 if (flg) { 5787 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5788 } else { 5789 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5790 } 5791 } 5792 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5793 } 5794 inassm--; 5795 PetscFunctionReturn(PETSC_SUCCESS); 5796 } 5797 5798 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5799 /*@ 5800 MatSetOption - Sets a parameter option for a matrix. Some options 5801 may be specific to certain storage formats. Some options 5802 determine how values will be inserted (or added). Sorted, 5803 row-oriented input will generally assemble the fastest. The default 5804 is row-oriented. 5805 5806 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5807 5808 Input Parameters: 5809 + mat - the matrix 5810 . op - the option, one of those listed below (and possibly others), 5811 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5812 5813 Options Describing Matrix Structure: 5814 + `MAT_SPD` - symmetric positive definite 5815 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5816 . `MAT_HERMITIAN` - transpose is the complex conjugation 5817 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5818 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5819 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5820 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5821 5822 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5823 do not need to be computed (usually at a high cost) 5824 5825 Options For Use with `MatSetValues()`: 5826 Insert a logically dense subblock, which can be 5827 . `MAT_ROW_ORIENTED` - row-oriented (default) 5828 5829 These options reflect the data you pass in with `MatSetValues()`; it has 5830 nothing to do with how the data is stored internally in the matrix 5831 data structure. 5832 5833 When (re)assembling a matrix, we can restrict the input for 5834 efficiency/debugging purposes. These options include 5835 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5836 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5837 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5838 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5839 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5840 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5841 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5842 performance for very large process counts. 5843 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5844 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5845 functions, instead sending only neighbor messages. 5846 5847 Level: intermediate 5848 5849 Notes: 5850 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5851 5852 Some options are relevant only for particular matrix types and 5853 are thus ignored by others. Other options are not supported by 5854 certain matrix types and will generate an error message if set. 5855 5856 If using Fortran to compute a matrix, one may need to 5857 use the column-oriented option (or convert to the row-oriented 5858 format). 5859 5860 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5861 that would generate a new entry in the nonzero structure is instead 5862 ignored. Thus, if memory has not already been allocated for this particular 5863 data, then the insertion is ignored. For dense matrices, in which 5864 the entire array is allocated, no entries are ever ignored. 5865 Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5866 5867 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5868 that would generate a new entry in the nonzero structure instead produces 5869 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 5870 5871 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5872 that would generate a new entry that has not been preallocated will 5873 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5874 only.) This is a useful flag when debugging matrix memory preallocation. 5875 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5876 5877 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5878 other processors should be dropped, rather than stashed. 5879 This is useful if you know that the "owning" processor is also 5880 always generating the correct matrix entries, so that PETSc need 5881 not transfer duplicate entries generated on another processor. 5882 5883 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5884 searches during matrix assembly. When this flag is set, the hash table 5885 is created during the first matrix assembly. This hash table is 5886 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5887 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5888 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5889 supported by `MATMPIBAIJ` format only. 5890 5891 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5892 are kept in the nonzero structure 5893 5894 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5895 a zero location in the matrix 5896 5897 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5898 5899 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5900 zero row routines and thus improves performance for very large process counts. 5901 5902 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5903 part of the matrix (since they should match the upper triangular part). 5904 5905 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5906 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5907 with finite difference schemes with non-periodic boundary conditions. 5908 5909 Developer Note: 5910 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5911 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 5912 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5913 not changed. 5914 5915 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5916 @*/ 5917 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5918 { 5919 PetscFunctionBegin; 5920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5921 if (op > 0) { 5922 PetscValidLogicalCollectiveEnum(mat, op, 2); 5923 PetscValidLogicalCollectiveBool(mat, flg, 3); 5924 } 5925 5926 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); 5927 5928 switch (op) { 5929 case MAT_FORCE_DIAGONAL_ENTRIES: 5930 mat->force_diagonals = flg; 5931 PetscFunctionReturn(PETSC_SUCCESS); 5932 case MAT_NO_OFF_PROC_ENTRIES: 5933 mat->nooffprocentries = flg; 5934 PetscFunctionReturn(PETSC_SUCCESS); 5935 case MAT_SUBSET_OFF_PROC_ENTRIES: 5936 mat->assembly_subset = flg; 5937 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5938 #if !defined(PETSC_HAVE_MPIUNI) 5939 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5940 #endif 5941 mat->stash.first_assembly_done = PETSC_FALSE; 5942 } 5943 PetscFunctionReturn(PETSC_SUCCESS); 5944 case MAT_NO_OFF_PROC_ZERO_ROWS: 5945 mat->nooffproczerorows = flg; 5946 PetscFunctionReturn(PETSC_SUCCESS); 5947 case MAT_SPD: 5948 if (flg) { 5949 mat->spd = PETSC_BOOL3_TRUE; 5950 mat->symmetric = PETSC_BOOL3_TRUE; 5951 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5952 } else { 5953 mat->spd = PETSC_BOOL3_FALSE; 5954 } 5955 break; 5956 case MAT_SYMMETRIC: 5957 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5958 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5959 #if !defined(PETSC_USE_COMPLEX) 5960 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5961 #endif 5962 break; 5963 case MAT_HERMITIAN: 5964 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5965 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5966 #if !defined(PETSC_USE_COMPLEX) 5967 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5968 #endif 5969 break; 5970 case MAT_STRUCTURALLY_SYMMETRIC: 5971 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5972 break; 5973 case MAT_SYMMETRY_ETERNAL: 5974 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"); 5975 mat->symmetry_eternal = flg; 5976 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5977 break; 5978 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5979 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"); 5980 mat->structural_symmetry_eternal = flg; 5981 break; 5982 case MAT_SPD_ETERNAL: 5983 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"); 5984 mat->spd_eternal = flg; 5985 if (flg) { 5986 mat->structural_symmetry_eternal = PETSC_TRUE; 5987 mat->symmetry_eternal = PETSC_TRUE; 5988 } 5989 break; 5990 case MAT_STRUCTURE_ONLY: 5991 mat->structure_only = flg; 5992 break; 5993 case MAT_SORTED_FULL: 5994 mat->sortedfull = flg; 5995 break; 5996 default: 5997 break; 5998 } 5999 PetscTryTypeMethod(mat, setoption, op, flg); 6000 PetscFunctionReturn(PETSC_SUCCESS); 6001 } 6002 6003 /*@ 6004 MatGetOption - Gets a parameter option that has been set for a matrix. 6005 6006 Logically Collective 6007 6008 Input Parameters: 6009 + mat - the matrix 6010 - op - the option, this only responds to certain options, check the code for which ones 6011 6012 Output Parameter: 6013 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6014 6015 Level: intermediate 6016 6017 Notes: 6018 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6019 6020 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6021 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6022 6023 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6024 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6025 @*/ 6026 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6027 { 6028 PetscFunctionBegin; 6029 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6030 PetscValidType(mat, 1); 6031 6032 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); 6033 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()"); 6034 6035 switch (op) { 6036 case MAT_NO_OFF_PROC_ENTRIES: 6037 *flg = mat->nooffprocentries; 6038 break; 6039 case MAT_NO_OFF_PROC_ZERO_ROWS: 6040 *flg = mat->nooffproczerorows; 6041 break; 6042 case MAT_SYMMETRIC: 6043 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6044 break; 6045 case MAT_HERMITIAN: 6046 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6047 break; 6048 case MAT_STRUCTURALLY_SYMMETRIC: 6049 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6050 break; 6051 case MAT_SPD: 6052 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6053 break; 6054 case MAT_SYMMETRY_ETERNAL: 6055 *flg = mat->symmetry_eternal; 6056 break; 6057 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6058 *flg = mat->symmetry_eternal; 6059 break; 6060 default: 6061 break; 6062 } 6063 PetscFunctionReturn(PETSC_SUCCESS); 6064 } 6065 6066 /*@ 6067 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6068 this routine retains the old nonzero structure. 6069 6070 Logically Collective 6071 6072 Input Parameter: 6073 . mat - the matrix 6074 6075 Level: intermediate 6076 6077 Note: 6078 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. 6079 See the Performance chapter of the users manual for information on preallocating matrices. 6080 6081 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6082 @*/ 6083 PetscErrorCode MatZeroEntries(Mat mat) 6084 { 6085 PetscFunctionBegin; 6086 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6087 PetscValidType(mat, 1); 6088 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6089 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"); 6090 MatCheckPreallocated(mat, 1); 6091 6092 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6093 PetscUseTypeMethod(mat, zeroentries); 6094 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6095 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6096 PetscFunctionReturn(PETSC_SUCCESS); 6097 } 6098 6099 /*@ 6100 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6101 of a set of rows and columns of a matrix. 6102 6103 Collective 6104 6105 Input Parameters: 6106 + mat - the matrix 6107 . numRows - the number of rows/columns to zero 6108 . rows - the global row indices 6109 . diag - value put in the diagonal of the eliminated rows 6110 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6111 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6112 6113 Level: intermediate 6114 6115 Notes: 6116 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6117 6118 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6119 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 6120 6121 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6122 Krylov method to take advantage of the known solution on the zeroed rows. 6123 6124 For the parallel case, all processes that share the matrix (i.e., 6125 those in the communicator used for matrix creation) MUST call this 6126 routine, regardless of whether any rows being zeroed are owned by 6127 them. 6128 6129 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6130 6131 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6132 list only rows local to itself). 6133 6134 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6135 6136 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6137 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6138 @*/ 6139 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6140 { 6141 PetscFunctionBegin; 6142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6143 PetscValidType(mat, 1); 6144 if (numRows) PetscAssertPointer(rows, 3); 6145 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6146 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6147 MatCheckPreallocated(mat, 1); 6148 6149 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6150 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6151 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6152 PetscFunctionReturn(PETSC_SUCCESS); 6153 } 6154 6155 /*@ 6156 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6157 of a set of rows and columns of a matrix. 6158 6159 Collective 6160 6161 Input Parameters: 6162 + mat - the matrix 6163 . is - the rows to zero 6164 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6165 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6166 - b - optional vector of right hand side, that will be adjusted by provided solution 6167 6168 Level: intermediate 6169 6170 Note: 6171 See `MatZeroRowsColumns()` for details on how this routine operates. 6172 6173 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6174 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6175 @*/ 6176 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6177 { 6178 PetscInt numRows; 6179 const PetscInt *rows; 6180 6181 PetscFunctionBegin; 6182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6183 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6184 PetscValidType(mat, 1); 6185 PetscValidType(is, 2); 6186 PetscCall(ISGetLocalSize(is, &numRows)); 6187 PetscCall(ISGetIndices(is, &rows)); 6188 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6189 PetscCall(ISRestoreIndices(is, &rows)); 6190 PetscFunctionReturn(PETSC_SUCCESS); 6191 } 6192 6193 /*@ 6194 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6195 of a set of rows of a matrix. 6196 6197 Collective 6198 6199 Input Parameters: 6200 + mat - the matrix 6201 . numRows - the number of rows to zero 6202 . rows - the global row indices 6203 . diag - value put in the diagonal of the zeroed rows 6204 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6205 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6206 6207 Level: intermediate 6208 6209 Notes: 6210 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6211 6212 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6213 6214 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6215 Krylov method to take advantage of the known solution on the zeroed rows. 6216 6217 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) 6218 from the matrix. 6219 6220 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6221 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 6222 formats this does not alter the nonzero structure. 6223 6224 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6225 of the matrix is not changed the values are 6226 merely zeroed. 6227 6228 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6229 formats can optionally remove the main diagonal entry from the 6230 nonzero structure as well, by passing 0.0 as the final argument). 6231 6232 For the parallel case, all processes that share the matrix (i.e., 6233 those in the communicator used for matrix creation) MUST call this 6234 routine, regardless of whether any rows being zeroed are owned by 6235 them. 6236 6237 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6238 list only rows local to itself). 6239 6240 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6241 owns that are to be zeroed. This saves a global synchronization in the implementation. 6242 6243 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6244 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6245 @*/ 6246 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6247 { 6248 PetscFunctionBegin; 6249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6250 PetscValidType(mat, 1); 6251 if (numRows) PetscAssertPointer(rows, 3); 6252 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6253 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6254 MatCheckPreallocated(mat, 1); 6255 6256 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6257 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6258 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6259 PetscFunctionReturn(PETSC_SUCCESS); 6260 } 6261 6262 /*@ 6263 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6264 of a set of rows of a matrix. 6265 6266 Collective 6267 6268 Input Parameters: 6269 + mat - the matrix 6270 . is - index set of rows to remove (if `NULL` then no row is removed) 6271 . diag - value put in all diagonals of eliminated rows 6272 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6273 - b - optional vector of right hand side, that will be adjusted by provided solution 6274 6275 Level: intermediate 6276 6277 Note: 6278 See `MatZeroRows()` for details on how this routine operates. 6279 6280 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6281 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6282 @*/ 6283 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6284 { 6285 PetscInt numRows = 0; 6286 const PetscInt *rows = NULL; 6287 6288 PetscFunctionBegin; 6289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6290 PetscValidType(mat, 1); 6291 if (is) { 6292 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6293 PetscCall(ISGetLocalSize(is, &numRows)); 6294 PetscCall(ISGetIndices(is, &rows)); 6295 } 6296 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6297 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6298 PetscFunctionReturn(PETSC_SUCCESS); 6299 } 6300 6301 /*@ 6302 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6303 of a set of rows of a matrix. These rows must be local to the process. 6304 6305 Collective 6306 6307 Input Parameters: 6308 + mat - the matrix 6309 . numRows - the number of rows to remove 6310 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6311 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6312 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6313 - b - optional vector of right hand side, that will be adjusted by provided solution 6314 6315 Level: intermediate 6316 6317 Notes: 6318 See `MatZeroRows()` for details on how this routine operates. 6319 6320 The grid coordinates are across the entire grid, not just the local portion 6321 6322 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6323 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6324 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6325 `DM_BOUNDARY_PERIODIC` boundary type. 6326 6327 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 6328 a single value per point) you can skip filling those indices. 6329 6330 Fortran Note: 6331 `idxm` and `idxn` should be declared as 6332 $ MatStencil idxm(4, m) 6333 and the values inserted using 6334 .vb 6335 idxm(MatStencil_i, 1) = i 6336 idxm(MatStencil_j, 1) = j 6337 idxm(MatStencil_k, 1) = k 6338 idxm(MatStencil_c, 1) = c 6339 etc 6340 .ve 6341 6342 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6343 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6344 @*/ 6345 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6346 { 6347 PetscInt dim = mat->stencil.dim; 6348 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6349 PetscInt *dims = mat->stencil.dims + 1; 6350 PetscInt *starts = mat->stencil.starts; 6351 PetscInt *dxm = (PetscInt *)rows; 6352 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6353 6354 PetscFunctionBegin; 6355 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6356 PetscValidType(mat, 1); 6357 if (numRows) PetscAssertPointer(rows, 3); 6358 6359 PetscCall(PetscMalloc1(numRows, &jdxm)); 6360 for (i = 0; i < numRows; ++i) { 6361 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6362 for (j = 0; j < 3 - sdim; ++j) dxm++; 6363 /* Local index in X dir */ 6364 tmp = *dxm++ - starts[0]; 6365 /* Loop over remaining dimensions */ 6366 for (j = 0; j < dim - 1; ++j) { 6367 /* If nonlocal, set index to be negative */ 6368 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6369 /* Update local index */ 6370 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6371 } 6372 /* Skip component slot if necessary */ 6373 if (mat->stencil.noc) dxm++; 6374 /* Local row number */ 6375 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6376 } 6377 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6378 PetscCall(PetscFree(jdxm)); 6379 PetscFunctionReturn(PETSC_SUCCESS); 6380 } 6381 6382 /*@ 6383 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6384 of a set of rows and columns of a matrix. 6385 6386 Collective 6387 6388 Input Parameters: 6389 + mat - the matrix 6390 . numRows - the number of rows/columns to remove 6391 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6392 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6393 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6394 - b - optional vector of right hand side, that will be adjusted by provided solution 6395 6396 Level: intermediate 6397 6398 Notes: 6399 See `MatZeroRowsColumns()` for details on how this routine operates. 6400 6401 The grid coordinates are across the entire grid, not just the local portion 6402 6403 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6404 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6405 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6406 `DM_BOUNDARY_PERIODIC` boundary type. 6407 6408 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 6409 a single value per point) you can skip filling those indices. 6410 6411 Fortran Note: 6412 `idxm` and `idxn` should be declared as 6413 $ MatStencil idxm(4, m) 6414 and the values inserted using 6415 .vb 6416 idxm(MatStencil_i, 1) = i 6417 idxm(MatStencil_j, 1) = j 6418 idxm(MatStencil_k, 1) = k 6419 idxm(MatStencil_c, 1) = c 6420 etc 6421 .ve 6422 6423 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6424 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6425 @*/ 6426 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6427 { 6428 PetscInt dim = mat->stencil.dim; 6429 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6430 PetscInt *dims = mat->stencil.dims + 1; 6431 PetscInt *starts = mat->stencil.starts; 6432 PetscInt *dxm = (PetscInt *)rows; 6433 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6434 6435 PetscFunctionBegin; 6436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6437 PetscValidType(mat, 1); 6438 if (numRows) PetscAssertPointer(rows, 3); 6439 6440 PetscCall(PetscMalloc1(numRows, &jdxm)); 6441 for (i = 0; i < numRows; ++i) { 6442 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6443 for (j = 0; j < 3 - sdim; ++j) dxm++; 6444 /* Local index in X dir */ 6445 tmp = *dxm++ - starts[0]; 6446 /* Loop over remaining dimensions */ 6447 for (j = 0; j < dim - 1; ++j) { 6448 /* If nonlocal, set index to be negative */ 6449 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6450 /* Update local index */ 6451 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6452 } 6453 /* Skip component slot if necessary */ 6454 if (mat->stencil.noc) dxm++; 6455 /* Local row number */ 6456 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6457 } 6458 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6459 PetscCall(PetscFree(jdxm)); 6460 PetscFunctionReturn(PETSC_SUCCESS); 6461 } 6462 6463 /*@C 6464 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6465 of a set of rows of a matrix; using local numbering of rows. 6466 6467 Collective 6468 6469 Input Parameters: 6470 + mat - the matrix 6471 . numRows - the number of rows to remove 6472 . rows - the local row indices 6473 . diag - value put in all diagonals of eliminated rows 6474 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6475 - b - optional vector of right hand side, that will be adjusted by provided solution 6476 6477 Level: intermediate 6478 6479 Notes: 6480 Before calling `MatZeroRowsLocal()`, the user must first set the 6481 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6482 6483 See `MatZeroRows()` for details on how this routine operates. 6484 6485 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6486 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6487 @*/ 6488 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6489 { 6490 PetscFunctionBegin; 6491 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6492 PetscValidType(mat, 1); 6493 if (numRows) PetscAssertPointer(rows, 3); 6494 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6495 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6496 MatCheckPreallocated(mat, 1); 6497 6498 if (mat->ops->zerorowslocal) { 6499 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6500 } else { 6501 IS is, newis; 6502 const PetscInt *newRows; 6503 6504 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6505 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6506 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6507 PetscCall(ISGetIndices(newis, &newRows)); 6508 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6509 PetscCall(ISRestoreIndices(newis, &newRows)); 6510 PetscCall(ISDestroy(&newis)); 6511 PetscCall(ISDestroy(&is)); 6512 } 6513 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6514 PetscFunctionReturn(PETSC_SUCCESS); 6515 } 6516 6517 /*@ 6518 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6519 of a set of rows of a matrix; using local numbering of rows. 6520 6521 Collective 6522 6523 Input Parameters: 6524 + mat - the matrix 6525 . is - index set of rows to remove 6526 . diag - value put in all diagonals of eliminated rows 6527 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6528 - b - optional vector of right hand side, that will be adjusted by provided solution 6529 6530 Level: intermediate 6531 6532 Notes: 6533 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6534 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6535 6536 See `MatZeroRows()` for details on how this routine operates. 6537 6538 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6539 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6540 @*/ 6541 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6542 { 6543 PetscInt numRows; 6544 const PetscInt *rows; 6545 6546 PetscFunctionBegin; 6547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6548 PetscValidType(mat, 1); 6549 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6550 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6551 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6552 MatCheckPreallocated(mat, 1); 6553 6554 PetscCall(ISGetLocalSize(is, &numRows)); 6555 PetscCall(ISGetIndices(is, &rows)); 6556 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6557 PetscCall(ISRestoreIndices(is, &rows)); 6558 PetscFunctionReturn(PETSC_SUCCESS); 6559 } 6560 6561 /*@ 6562 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6563 of a set of rows and columns of a matrix; using local numbering of rows. 6564 6565 Collective 6566 6567 Input Parameters: 6568 + mat - the matrix 6569 . numRows - the number of rows to remove 6570 . rows - the global row indices 6571 . diag - value put in all diagonals of eliminated rows 6572 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6573 - b - optional vector of right hand side, that will be adjusted by provided solution 6574 6575 Level: intermediate 6576 6577 Notes: 6578 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6579 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6580 6581 See `MatZeroRowsColumns()` for details on how this routine operates. 6582 6583 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6584 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6585 @*/ 6586 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6587 { 6588 IS is, newis; 6589 const PetscInt *newRows; 6590 6591 PetscFunctionBegin; 6592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6593 PetscValidType(mat, 1); 6594 if (numRows) PetscAssertPointer(rows, 3); 6595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6597 MatCheckPreallocated(mat, 1); 6598 6599 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6600 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6601 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6602 PetscCall(ISGetIndices(newis, &newRows)); 6603 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6604 PetscCall(ISRestoreIndices(newis, &newRows)); 6605 PetscCall(ISDestroy(&newis)); 6606 PetscCall(ISDestroy(&is)); 6607 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6608 PetscFunctionReturn(PETSC_SUCCESS); 6609 } 6610 6611 /*@ 6612 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6613 of a set of rows and columns of a matrix; using local numbering of rows. 6614 6615 Collective 6616 6617 Input Parameters: 6618 + mat - the matrix 6619 . is - index set of rows to remove 6620 . diag - value put in all diagonals of eliminated rows 6621 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6622 - b - optional vector of right hand side, that will be adjusted by provided solution 6623 6624 Level: intermediate 6625 6626 Notes: 6627 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6628 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6629 6630 See `MatZeroRowsColumns()` for details on how this routine operates. 6631 6632 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6633 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6634 @*/ 6635 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6636 { 6637 PetscInt numRows; 6638 const PetscInt *rows; 6639 6640 PetscFunctionBegin; 6641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6642 PetscValidType(mat, 1); 6643 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6644 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6645 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6646 MatCheckPreallocated(mat, 1); 6647 6648 PetscCall(ISGetLocalSize(is, &numRows)); 6649 PetscCall(ISGetIndices(is, &rows)); 6650 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6651 PetscCall(ISRestoreIndices(is, &rows)); 6652 PetscFunctionReturn(PETSC_SUCCESS); 6653 } 6654 6655 /*@C 6656 MatGetSize - Returns the numbers of rows and columns in a matrix. 6657 6658 Not Collective 6659 6660 Input Parameter: 6661 . mat - the matrix 6662 6663 Output Parameters: 6664 + m - the number of global rows 6665 - n - the number of global columns 6666 6667 Level: beginner 6668 6669 Note: 6670 Both output parameters can be `NULL` on input. 6671 6672 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6673 @*/ 6674 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6675 { 6676 PetscFunctionBegin; 6677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6678 if (m) *m = mat->rmap->N; 6679 if (n) *n = mat->cmap->N; 6680 PetscFunctionReturn(PETSC_SUCCESS); 6681 } 6682 6683 /*@C 6684 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6685 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6686 6687 Not Collective 6688 6689 Input Parameter: 6690 . mat - the matrix 6691 6692 Output Parameters: 6693 + m - the number of local rows, use `NULL` to not obtain this value 6694 - n - the number of local columns, use `NULL` to not obtain this value 6695 6696 Level: beginner 6697 6698 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6699 @*/ 6700 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6701 { 6702 PetscFunctionBegin; 6703 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6704 if (m) PetscAssertPointer(m, 2); 6705 if (n) PetscAssertPointer(n, 3); 6706 if (m) *m = mat->rmap->n; 6707 if (n) *n = mat->cmap->n; 6708 PetscFunctionReturn(PETSC_SUCCESS); 6709 } 6710 6711 /*@C 6712 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6713 vector one multiplies this matrix by that are owned by this processor. 6714 6715 Not Collective, unless matrix has not been allocated, then collective 6716 6717 Input Parameter: 6718 . mat - the matrix 6719 6720 Output Parameters: 6721 + m - the global index of the first local column, use `NULL` to not obtain this value 6722 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6723 6724 Level: developer 6725 6726 Note: 6727 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6728 Layouts](sec_matlayout) for details on matrix layouts. 6729 6730 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6731 @*/ 6732 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6733 { 6734 PetscFunctionBegin; 6735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6736 PetscValidType(mat, 1); 6737 if (m) PetscAssertPointer(m, 2); 6738 if (n) PetscAssertPointer(n, 3); 6739 MatCheckPreallocated(mat, 1); 6740 if (m) *m = mat->cmap->rstart; 6741 if (n) *n = mat->cmap->rend; 6742 PetscFunctionReturn(PETSC_SUCCESS); 6743 } 6744 6745 /*@C 6746 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6747 this MPI process. 6748 6749 Not Collective 6750 6751 Input Parameter: 6752 . mat - the matrix 6753 6754 Output Parameters: 6755 + m - the global index of the first local row, use `NULL` to not obtain this value 6756 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6757 6758 Level: beginner 6759 6760 Note: 6761 For all matrices it returns the range of matrix rows associated with rows of a vector that 6762 would contain the result of a matrix vector product with this matrix. See [Matrix 6763 Layouts](sec_matlayout) for details on matrix layouts. 6764 6765 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6766 `PetscLayout` 6767 @*/ 6768 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6769 { 6770 PetscFunctionBegin; 6771 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6772 PetscValidType(mat, 1); 6773 if (m) PetscAssertPointer(m, 2); 6774 if (n) PetscAssertPointer(n, 3); 6775 MatCheckPreallocated(mat, 1); 6776 if (m) *m = mat->rmap->rstart; 6777 if (n) *n = mat->rmap->rend; 6778 PetscFunctionReturn(PETSC_SUCCESS); 6779 } 6780 6781 /*@C 6782 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6783 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6784 6785 Not Collective, unless matrix has not been allocated 6786 6787 Input Parameter: 6788 . mat - the matrix 6789 6790 Output Parameter: 6791 . ranges - start of each processors portion plus one more than the total length at the end 6792 6793 Level: beginner 6794 6795 Note: 6796 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6797 would contain the result of a matrix vector product with this matrix. See [Matrix 6798 Layouts](sec_matlayout) for details on matrix layouts. 6799 6800 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6801 @*/ 6802 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6803 { 6804 PetscFunctionBegin; 6805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6806 PetscValidType(mat, 1); 6807 MatCheckPreallocated(mat, 1); 6808 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6809 PetscFunctionReturn(PETSC_SUCCESS); 6810 } 6811 6812 /*@C 6813 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6814 vector one multiplies this vector by that are owned by each processor. 6815 6816 Not Collective, unless matrix has not been allocated 6817 6818 Input Parameter: 6819 . mat - the matrix 6820 6821 Output Parameter: 6822 . ranges - start of each processors portion plus one more than the total length at the end 6823 6824 Level: beginner 6825 6826 Note: 6827 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6828 Layouts](sec_matlayout) for details on matrix layouts. 6829 6830 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6831 @*/ 6832 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6833 { 6834 PetscFunctionBegin; 6835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6836 PetscValidType(mat, 1); 6837 MatCheckPreallocated(mat, 1); 6838 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6839 PetscFunctionReturn(PETSC_SUCCESS); 6840 } 6841 6842 /*@C 6843 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6844 6845 Not Collective 6846 6847 Input Parameter: 6848 . A - matrix 6849 6850 Output Parameters: 6851 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6852 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6853 6854 Level: intermediate 6855 6856 Note: 6857 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6858 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6859 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6860 details on matrix layouts. 6861 6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6863 @*/ 6864 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6865 { 6866 PetscErrorCode (*f)(Mat, IS *, IS *); 6867 6868 PetscFunctionBegin; 6869 MatCheckPreallocated(A, 1); 6870 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6871 if (f) { 6872 PetscCall((*f)(A, rows, cols)); 6873 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6874 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6875 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6876 } 6877 PetscFunctionReturn(PETSC_SUCCESS); 6878 } 6879 6880 /*@C 6881 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6882 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6883 to complete the factorization. 6884 6885 Collective 6886 6887 Input Parameters: 6888 + fact - the factorized matrix obtained with `MatGetFactor()` 6889 . mat - the matrix 6890 . row - row permutation 6891 . col - column permutation 6892 - info - structure containing 6893 .vb 6894 levels - number of levels of fill. 6895 expected fill - as ratio of original fill. 6896 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6897 missing diagonal entries) 6898 .ve 6899 6900 Level: developer 6901 6902 Notes: 6903 See [Matrix Factorization](sec_matfactor) for additional information. 6904 6905 Most users should employ the `KSP` interface for linear solvers 6906 instead of working directly with matrix algebra routines such as this. 6907 See, e.g., `KSPCreate()`. 6908 6909 Uses the definition of level of fill as in Y. Saad, 2003 6910 6911 Developer Note: 6912 The Fortran interface is not autogenerated as the 6913 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6914 6915 References: 6916 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6917 6918 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6919 `MatGetOrdering()`, `MatFactorInfo` 6920 @*/ 6921 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6922 { 6923 PetscFunctionBegin; 6924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6925 PetscValidType(mat, 2); 6926 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6927 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6928 PetscAssertPointer(info, 5); 6929 PetscAssertPointer(fact, 1); 6930 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6931 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6932 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6933 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6934 MatCheckPreallocated(mat, 2); 6935 6936 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6937 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6938 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6939 PetscFunctionReturn(PETSC_SUCCESS); 6940 } 6941 6942 /*@C 6943 MatICCFactorSymbolic - Performs symbolic incomplete 6944 Cholesky factorization for a symmetric matrix. Use 6945 `MatCholeskyFactorNumeric()` to complete the factorization. 6946 6947 Collective 6948 6949 Input Parameters: 6950 + fact - the factorized matrix obtained with `MatGetFactor()` 6951 . mat - the matrix to be factored 6952 . perm - row and column permutation 6953 - info - structure containing 6954 .vb 6955 levels - number of levels of fill. 6956 expected fill - as ratio of original fill. 6957 .ve 6958 6959 Level: developer 6960 6961 Notes: 6962 Most users should employ the `KSP` interface for linear solvers 6963 instead of working directly with matrix algebra routines such as this. 6964 See, e.g., `KSPCreate()`. 6965 6966 This uses the definition of level of fill as in Y. Saad, 2003 6967 6968 Developer Note: 6969 The Fortran interface is not autogenerated as the 6970 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6971 6972 References: 6973 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6974 6975 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6976 @*/ 6977 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6978 { 6979 PetscFunctionBegin; 6980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6981 PetscValidType(mat, 2); 6982 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6983 PetscAssertPointer(info, 4); 6984 PetscAssertPointer(fact, 1); 6985 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6986 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6987 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6988 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6989 MatCheckPreallocated(mat, 2); 6990 6991 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6992 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6993 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6994 PetscFunctionReturn(PETSC_SUCCESS); 6995 } 6996 6997 /*@C 6998 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6999 points to an array of valid matrices, they may be reused to store the new 7000 submatrices. 7001 7002 Collective 7003 7004 Input Parameters: 7005 + mat - the matrix 7006 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7007 . irow - index set of rows to extract 7008 . icol - index set of columns to extract 7009 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7010 7011 Output Parameter: 7012 . submat - the array of submatrices 7013 7014 Level: advanced 7015 7016 Notes: 7017 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7018 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7019 to extract a parallel submatrix. 7020 7021 Some matrix types place restrictions on the row and column 7022 indices, such as that they be sorted or that they be equal to each other. 7023 7024 The index sets may not have duplicate entries. 7025 7026 When extracting submatrices from a parallel matrix, each processor can 7027 form a different submatrix by setting the rows and columns of its 7028 individual index sets according to the local submatrix desired. 7029 7030 When finished using the submatrices, the user should destroy 7031 them with `MatDestroySubMatrices()`. 7032 7033 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7034 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7035 7036 This routine creates the matrices in submat; you should NOT create them before 7037 calling it. It also allocates the array of matrix pointers submat. 7038 7039 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7040 request one row/column in a block, they must request all rows/columns that are in 7041 that block. For example, if the block size is 2 you cannot request just row 0 and 7042 column 0. 7043 7044 Fortran Note: 7045 The Fortran interface is slightly different from that given below; it 7046 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7047 7048 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7049 @*/ 7050 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7051 { 7052 PetscInt i; 7053 PetscBool eq; 7054 7055 PetscFunctionBegin; 7056 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7057 PetscValidType(mat, 1); 7058 if (n) { 7059 PetscAssertPointer(irow, 3); 7060 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7061 PetscAssertPointer(icol, 4); 7062 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7063 } 7064 PetscAssertPointer(submat, 6); 7065 if (n && scall == MAT_REUSE_MATRIX) { 7066 PetscAssertPointer(*submat, 6); 7067 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7068 } 7069 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7070 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7071 MatCheckPreallocated(mat, 1); 7072 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7073 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7074 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7075 for (i = 0; i < n; i++) { 7076 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7077 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7078 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7079 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7080 if (mat->boundtocpu && mat->bindingpropagates) { 7081 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7082 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7083 } 7084 #endif 7085 } 7086 PetscFunctionReturn(PETSC_SUCCESS); 7087 } 7088 7089 /*@C 7090 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7091 7092 Collective 7093 7094 Input Parameters: 7095 + mat - the matrix 7096 . n - the number of submatrixes to be extracted 7097 . irow - index set of rows to extract 7098 . icol - index set of columns to extract 7099 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7100 7101 Output Parameter: 7102 . submat - the array of submatrices 7103 7104 Level: advanced 7105 7106 Note: 7107 This is used by `PCGASM` 7108 7109 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7110 @*/ 7111 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7112 { 7113 PetscInt i; 7114 PetscBool eq; 7115 7116 PetscFunctionBegin; 7117 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7118 PetscValidType(mat, 1); 7119 if (n) { 7120 PetscAssertPointer(irow, 3); 7121 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7122 PetscAssertPointer(icol, 4); 7123 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7124 } 7125 PetscAssertPointer(submat, 6); 7126 if (n && scall == MAT_REUSE_MATRIX) { 7127 PetscAssertPointer(*submat, 6); 7128 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7129 } 7130 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7131 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7132 MatCheckPreallocated(mat, 1); 7133 7134 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7135 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7136 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7137 for (i = 0; i < n; i++) { 7138 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7139 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7140 } 7141 PetscFunctionReturn(PETSC_SUCCESS); 7142 } 7143 7144 /*@C 7145 MatDestroyMatrices - Destroys an array of matrices. 7146 7147 Collective 7148 7149 Input Parameters: 7150 + n - the number of local matrices 7151 - mat - the matrices (this is a pointer to the array of matrices) 7152 7153 Level: advanced 7154 7155 Note: 7156 Frees not only the matrices, but also the array that contains the matrices 7157 7158 Fortran Note: 7159 This does not free the array. 7160 7161 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7162 @*/ 7163 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7164 { 7165 PetscInt i; 7166 7167 PetscFunctionBegin; 7168 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7169 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7170 PetscAssertPointer(mat, 2); 7171 7172 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7173 7174 /* memory is allocated even if n = 0 */ 7175 PetscCall(PetscFree(*mat)); 7176 PetscFunctionReturn(PETSC_SUCCESS); 7177 } 7178 7179 /*@C 7180 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7181 7182 Collective 7183 7184 Input Parameters: 7185 + n - the number of local matrices 7186 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7187 sequence of `MatCreateSubMatrices()`) 7188 7189 Level: advanced 7190 7191 Note: 7192 Frees not only the matrices, but also the array that contains the matrices 7193 7194 Fortran Note: 7195 This does not free the array. 7196 7197 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7198 @*/ 7199 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7200 { 7201 Mat mat0; 7202 7203 PetscFunctionBegin; 7204 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7205 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7206 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7207 PetscAssertPointer(mat, 2); 7208 7209 mat0 = (*mat)[0]; 7210 if (mat0 && mat0->ops->destroysubmatrices) { 7211 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7212 } else { 7213 PetscCall(MatDestroyMatrices(n, mat)); 7214 } 7215 PetscFunctionReturn(PETSC_SUCCESS); 7216 } 7217 7218 /*@C 7219 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7220 7221 Collective 7222 7223 Input Parameter: 7224 . mat - the matrix 7225 7226 Output Parameter: 7227 . matstruct - the sequential matrix with the nonzero structure of mat 7228 7229 Level: developer 7230 7231 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7232 @*/ 7233 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7234 { 7235 PetscFunctionBegin; 7236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7237 PetscAssertPointer(matstruct, 2); 7238 7239 PetscValidType(mat, 1); 7240 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7241 MatCheckPreallocated(mat, 1); 7242 7243 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7244 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7245 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7246 PetscFunctionReturn(PETSC_SUCCESS); 7247 } 7248 7249 /*@C 7250 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7251 7252 Collective 7253 7254 Input Parameter: 7255 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7256 sequence of `MatGetSeqNonzeroStructure()`) 7257 7258 Level: advanced 7259 7260 Note: 7261 Frees not only the matrices, but also the array that contains the matrices 7262 7263 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7264 @*/ 7265 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7266 { 7267 PetscFunctionBegin; 7268 PetscAssertPointer(mat, 1); 7269 PetscCall(MatDestroy(mat)); 7270 PetscFunctionReturn(PETSC_SUCCESS); 7271 } 7272 7273 /*@ 7274 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7275 replaces the index sets by larger ones that represent submatrices with 7276 additional overlap. 7277 7278 Collective 7279 7280 Input Parameters: 7281 + mat - the matrix 7282 . n - the number of index sets 7283 . is - the array of index sets (these index sets will changed during the call) 7284 - ov - the additional overlap requested 7285 7286 Options Database Key: 7287 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7288 7289 Level: developer 7290 7291 Note: 7292 The computed overlap preserves the matrix block sizes when the blocks are square. 7293 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7294 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7295 7296 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7297 @*/ 7298 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7299 { 7300 PetscInt i, bs, cbs; 7301 7302 PetscFunctionBegin; 7303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7304 PetscValidType(mat, 1); 7305 PetscValidLogicalCollectiveInt(mat, n, 2); 7306 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7307 if (n) { 7308 PetscAssertPointer(is, 3); 7309 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7310 } 7311 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7312 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7313 MatCheckPreallocated(mat, 1); 7314 7315 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7316 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7317 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7318 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7319 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7320 if (bs == cbs) { 7321 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7322 } 7323 PetscFunctionReturn(PETSC_SUCCESS); 7324 } 7325 7326 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7327 7328 /*@ 7329 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7330 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7331 additional overlap. 7332 7333 Collective 7334 7335 Input Parameters: 7336 + mat - the matrix 7337 . n - the number of index sets 7338 . is - the array of index sets (these index sets will changed during the call) 7339 - ov - the additional overlap requested 7340 7341 ` Options Database Key: 7342 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7343 7344 Level: developer 7345 7346 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7347 @*/ 7348 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7349 { 7350 PetscInt i; 7351 7352 PetscFunctionBegin; 7353 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7354 PetscValidType(mat, 1); 7355 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7356 if (n) { 7357 PetscAssertPointer(is, 3); 7358 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7359 } 7360 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7361 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7362 MatCheckPreallocated(mat, 1); 7363 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7364 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7365 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7366 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7367 PetscFunctionReturn(PETSC_SUCCESS); 7368 } 7369 7370 /*@ 7371 MatGetBlockSize - Returns the matrix block size. 7372 7373 Not Collective 7374 7375 Input Parameter: 7376 . mat - the matrix 7377 7378 Output Parameter: 7379 . bs - block size 7380 7381 Level: intermediate 7382 7383 Notes: 7384 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7385 7386 If the block size has not been set yet this routine returns 1. 7387 7388 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7389 @*/ 7390 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7391 { 7392 PetscFunctionBegin; 7393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7394 PetscAssertPointer(bs, 2); 7395 *bs = PetscAbs(mat->rmap->bs); 7396 PetscFunctionReturn(PETSC_SUCCESS); 7397 } 7398 7399 /*@ 7400 MatGetBlockSizes - Returns the matrix block row and column sizes. 7401 7402 Not Collective 7403 7404 Input Parameter: 7405 . mat - the matrix 7406 7407 Output Parameters: 7408 + rbs - row block size 7409 - cbs - column block size 7410 7411 Level: intermediate 7412 7413 Notes: 7414 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7415 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7416 7417 If a block size has not been set yet this routine returns 1. 7418 7419 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7420 @*/ 7421 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7422 { 7423 PetscFunctionBegin; 7424 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7425 if (rbs) PetscAssertPointer(rbs, 2); 7426 if (cbs) PetscAssertPointer(cbs, 3); 7427 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7428 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7429 PetscFunctionReturn(PETSC_SUCCESS); 7430 } 7431 7432 /*@ 7433 MatSetBlockSize - Sets the matrix block size. 7434 7435 Logically Collective 7436 7437 Input Parameters: 7438 + mat - the matrix 7439 - bs - block size 7440 7441 Level: intermediate 7442 7443 Notes: 7444 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7445 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7446 7447 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7448 is compatible with the matrix local sizes. 7449 7450 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7451 @*/ 7452 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7453 { 7454 PetscFunctionBegin; 7455 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7456 PetscValidLogicalCollectiveInt(mat, bs, 2); 7457 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7458 PetscFunctionReturn(PETSC_SUCCESS); 7459 } 7460 7461 typedef struct { 7462 PetscInt n; 7463 IS *is; 7464 Mat *mat; 7465 PetscObjectState nonzerostate; 7466 Mat C; 7467 } EnvelopeData; 7468 7469 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7470 { 7471 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7472 PetscCall(PetscFree(edata->is)); 7473 PetscCall(PetscFree(edata)); 7474 return PETSC_SUCCESS; 7475 } 7476 7477 /*@ 7478 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7479 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7480 7481 Collective 7482 7483 Input Parameter: 7484 . mat - the matrix 7485 7486 Level: intermediate 7487 7488 Notes: 7489 There can be zeros within the blocks 7490 7491 The blocks can overlap between processes, including laying on more than two processes 7492 7493 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7494 @*/ 7495 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7496 { 7497 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7498 PetscInt *diag, *odiag, sc; 7499 VecScatter scatter; 7500 PetscScalar *seqv; 7501 const PetscScalar *parv; 7502 const PetscInt *ia, *ja; 7503 PetscBool set, flag, done; 7504 Mat AA = mat, A; 7505 MPI_Comm comm; 7506 PetscMPIInt rank, size, tag; 7507 MPI_Status status; 7508 PetscContainer container; 7509 EnvelopeData *edata; 7510 Vec seq, par; 7511 IS isglobal; 7512 7513 PetscFunctionBegin; 7514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7515 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7516 if (!set || !flag) { 7517 /* TODO: only needs nonzero structure of transpose */ 7518 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7519 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7520 } 7521 PetscCall(MatAIJGetLocalMat(AA, &A)); 7522 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7523 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7524 7525 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7526 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7527 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7528 PetscCallMPI(MPI_Comm_size(comm, &size)); 7529 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7530 7531 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7532 7533 if (rank > 0) { 7534 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7535 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7536 } 7537 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7538 for (i = 0; i < n; i++) { 7539 env = PetscMax(env, ja[ia[i + 1] - 1]); 7540 II = rstart + i; 7541 if (env == II) { 7542 starts[lblocks] = tbs; 7543 sizes[lblocks++] = 1 + II - tbs; 7544 tbs = 1 + II; 7545 } 7546 } 7547 if (rank < size - 1) { 7548 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7549 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7550 } 7551 7552 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7553 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7554 PetscCall(MatDestroy(&A)); 7555 7556 PetscCall(PetscNew(&edata)); 7557 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7558 edata->n = lblocks; 7559 /* create IS needed for extracting blocks from the original matrix */ 7560 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7561 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7562 7563 /* Create the resulting inverse matrix structure with preallocation information */ 7564 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7565 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7566 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7567 PetscCall(MatSetType(edata->C, MATAIJ)); 7568 7569 /* Communicate the start and end of each row, from each block to the correct rank */ 7570 /* TODO: Use PetscSF instead of VecScatter */ 7571 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7572 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7573 PetscCall(VecGetArrayWrite(seq, &seqv)); 7574 for (PetscInt i = 0; i < lblocks; i++) { 7575 for (PetscInt j = 0; j < sizes[i]; j++) { 7576 seqv[cnt] = starts[i]; 7577 seqv[cnt + 1] = starts[i] + sizes[i]; 7578 cnt += 2; 7579 } 7580 } 7581 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7582 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7583 sc -= cnt; 7584 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7585 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7586 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7587 PetscCall(ISDestroy(&isglobal)); 7588 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7589 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7590 PetscCall(VecScatterDestroy(&scatter)); 7591 PetscCall(VecDestroy(&seq)); 7592 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7593 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7594 PetscCall(VecGetArrayRead(par, &parv)); 7595 cnt = 0; 7596 PetscCall(MatGetSize(mat, NULL, &n)); 7597 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7598 PetscInt start, end, d = 0, od = 0; 7599 7600 start = (PetscInt)PetscRealPart(parv[cnt]); 7601 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7602 cnt += 2; 7603 7604 if (start < cstart) { 7605 od += cstart - start + n - cend; 7606 d += cend - cstart; 7607 } else if (start < cend) { 7608 od += n - cend; 7609 d += cend - start; 7610 } else od += n - start; 7611 if (end <= cstart) { 7612 od -= cstart - end + n - cend; 7613 d -= cend - cstart; 7614 } else if (end < cend) { 7615 od -= n - cend; 7616 d -= cend - end; 7617 } else od -= n - end; 7618 7619 odiag[i] = od; 7620 diag[i] = d; 7621 } 7622 PetscCall(VecRestoreArrayRead(par, &parv)); 7623 PetscCall(VecDestroy(&par)); 7624 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7625 PetscCall(PetscFree2(diag, odiag)); 7626 PetscCall(PetscFree2(sizes, starts)); 7627 7628 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7629 PetscCall(PetscContainerSetPointer(container, edata)); 7630 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7631 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7632 PetscCall(PetscObjectDereference((PetscObject)container)); 7633 PetscFunctionReturn(PETSC_SUCCESS); 7634 } 7635 7636 /*@ 7637 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7638 7639 Collective 7640 7641 Input Parameters: 7642 + A - the matrix 7643 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7644 7645 Output Parameter: 7646 . C - matrix with inverted block diagonal of `A` 7647 7648 Level: advanced 7649 7650 Note: 7651 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7652 7653 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7654 @*/ 7655 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7656 { 7657 PetscContainer container; 7658 EnvelopeData *edata; 7659 PetscObjectState nonzerostate; 7660 7661 PetscFunctionBegin; 7662 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7663 if (!container) { 7664 PetscCall(MatComputeVariableBlockEnvelope(A)); 7665 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7666 } 7667 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7668 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7669 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7670 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7671 7672 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7673 *C = edata->C; 7674 7675 for (PetscInt i = 0; i < edata->n; i++) { 7676 Mat D; 7677 PetscScalar *dvalues; 7678 7679 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7680 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7681 PetscCall(MatSeqDenseInvert(D)); 7682 PetscCall(MatDenseGetArray(D, &dvalues)); 7683 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7684 PetscCall(MatDestroy(&D)); 7685 } 7686 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7687 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7688 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7689 PetscFunctionReturn(PETSC_SUCCESS); 7690 } 7691 7692 /*@ 7693 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7694 7695 Logically Collective 7696 7697 Input Parameters: 7698 + mat - the matrix 7699 . nblocks - the number of blocks on this process, each block can only exist on a single process 7700 - bsizes - the block sizes 7701 7702 Level: intermediate 7703 7704 Notes: 7705 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7706 7707 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. 7708 7709 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7710 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7711 @*/ 7712 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7713 { 7714 PetscInt i, ncnt = 0, nlocal; 7715 7716 PetscFunctionBegin; 7717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7718 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7719 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7720 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7721 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); 7722 PetscCall(PetscFree(mat->bsizes)); 7723 mat->nblocks = nblocks; 7724 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7725 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7726 PetscFunctionReturn(PETSC_SUCCESS); 7727 } 7728 7729 /*@C 7730 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7731 7732 Logically Collective; No Fortran Support 7733 7734 Input Parameter: 7735 . mat - the matrix 7736 7737 Output Parameters: 7738 + nblocks - the number of blocks on this process 7739 - bsizes - the block sizes 7740 7741 Level: intermediate 7742 7743 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7744 @*/ 7745 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7746 { 7747 PetscFunctionBegin; 7748 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7749 *nblocks = mat->nblocks; 7750 *bsizes = mat->bsizes; 7751 PetscFunctionReturn(PETSC_SUCCESS); 7752 } 7753 7754 /*@ 7755 MatSetBlockSizes - Sets the matrix block row and column sizes. 7756 7757 Logically Collective 7758 7759 Input Parameters: 7760 + mat - the matrix 7761 . rbs - row block size 7762 - cbs - column block size 7763 7764 Level: intermediate 7765 7766 Notes: 7767 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7768 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7769 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7770 7771 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7772 are compatible with the matrix local sizes. 7773 7774 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7775 7776 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7777 @*/ 7778 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7779 { 7780 PetscFunctionBegin; 7781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7782 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7783 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7784 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7785 if (mat->rmap->refcnt) { 7786 ISLocalToGlobalMapping l2g = NULL; 7787 PetscLayout nmap = NULL; 7788 7789 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7790 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7791 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7792 mat->rmap = nmap; 7793 mat->rmap->mapping = l2g; 7794 } 7795 if (mat->cmap->refcnt) { 7796 ISLocalToGlobalMapping l2g = NULL; 7797 PetscLayout nmap = NULL; 7798 7799 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7800 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7801 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7802 mat->cmap = nmap; 7803 mat->cmap->mapping = l2g; 7804 } 7805 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7806 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7807 PetscFunctionReturn(PETSC_SUCCESS); 7808 } 7809 7810 /*@ 7811 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7812 7813 Logically Collective 7814 7815 Input Parameters: 7816 + mat - the matrix 7817 . fromRow - matrix from which to copy row block size 7818 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7819 7820 Level: developer 7821 7822 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7823 @*/ 7824 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7825 { 7826 PetscFunctionBegin; 7827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7828 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7829 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7830 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7831 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7832 PetscFunctionReturn(PETSC_SUCCESS); 7833 } 7834 7835 /*@ 7836 MatResidual - Default routine to calculate the residual r = b - Ax 7837 7838 Collective 7839 7840 Input Parameters: 7841 + mat - the matrix 7842 . b - the right-hand-side 7843 - x - the approximate solution 7844 7845 Output Parameter: 7846 . r - location to store the residual 7847 7848 Level: developer 7849 7850 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7851 @*/ 7852 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7853 { 7854 PetscFunctionBegin; 7855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7856 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7857 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7858 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7859 PetscValidType(mat, 1); 7860 MatCheckPreallocated(mat, 1); 7861 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7862 if (!mat->ops->residual) { 7863 PetscCall(MatMult(mat, x, r)); 7864 PetscCall(VecAYPX(r, -1.0, b)); 7865 } else { 7866 PetscUseTypeMethod(mat, residual, b, x, r); 7867 } 7868 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7869 PetscFunctionReturn(PETSC_SUCCESS); 7870 } 7871 7872 /*MC 7873 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7874 7875 Synopsis: 7876 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7877 7878 Not Collective 7879 7880 Input Parameters: 7881 + A - the matrix 7882 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7883 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7884 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7885 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7886 always used. 7887 7888 Output Parameters: 7889 + n - number of local rows in the (possibly compressed) matrix 7890 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7891 . ja - the column indices 7892 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7893 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7894 7895 Level: developer 7896 7897 Note: 7898 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7899 7900 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7901 M*/ 7902 7903 /*MC 7904 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7905 7906 Synopsis: 7907 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7908 7909 Not Collective 7910 7911 Input Parameters: 7912 + A - the matrix 7913 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7914 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7915 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7916 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7917 always used. 7918 . n - number of local rows in the (possibly compressed) matrix 7919 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7920 . ja - the column indices 7921 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7922 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7923 7924 Level: developer 7925 7926 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7927 M*/ 7928 7929 /*@C 7930 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7931 7932 Collective 7933 7934 Input Parameters: 7935 + mat - the matrix 7936 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7937 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7938 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7939 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7940 always used. 7941 7942 Output Parameters: 7943 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7944 . 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 7945 . ja - the column indices, use `NULL` if not needed 7946 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7947 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7948 7949 Level: developer 7950 7951 Notes: 7952 You CANNOT change any of the ia[] or ja[] values. 7953 7954 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7955 7956 Fortran Notes: 7957 Use 7958 .vb 7959 PetscInt, pointer :: ia(:),ja(:) 7960 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7961 ! Access the ith and jth entries via ia(i) and ja(j) 7962 .ve 7963 7964 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7965 7966 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7967 @*/ 7968 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7969 { 7970 PetscFunctionBegin; 7971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7972 PetscValidType(mat, 1); 7973 if (n) PetscAssertPointer(n, 5); 7974 if (ia) PetscAssertPointer(ia, 6); 7975 if (ja) PetscAssertPointer(ja, 7); 7976 if (done) PetscAssertPointer(done, 8); 7977 MatCheckPreallocated(mat, 1); 7978 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7979 else { 7980 if (done) *done = PETSC_TRUE; 7981 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7982 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7983 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7984 } 7985 PetscFunctionReturn(PETSC_SUCCESS); 7986 } 7987 7988 /*@C 7989 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7990 7991 Collective 7992 7993 Input Parameters: 7994 + mat - the matrix 7995 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7996 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7997 symmetrized 7998 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7999 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8000 always used. 8001 . n - number of columns in the (possibly compressed) matrix 8002 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8003 - ja - the row indices 8004 8005 Output Parameter: 8006 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8007 8008 Level: developer 8009 8010 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8011 @*/ 8012 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8013 { 8014 PetscFunctionBegin; 8015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8016 PetscValidType(mat, 1); 8017 PetscAssertPointer(n, 5); 8018 if (ia) PetscAssertPointer(ia, 6); 8019 if (ja) PetscAssertPointer(ja, 7); 8020 PetscAssertPointer(done, 8); 8021 MatCheckPreallocated(mat, 1); 8022 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8023 else { 8024 *done = PETSC_TRUE; 8025 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8026 } 8027 PetscFunctionReturn(PETSC_SUCCESS); 8028 } 8029 8030 /*@C 8031 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8032 8033 Collective 8034 8035 Input Parameters: 8036 + mat - the matrix 8037 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8038 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8039 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8040 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8041 always used. 8042 . n - size of (possibly compressed) matrix 8043 . ia - the row pointers 8044 - ja - the column indices 8045 8046 Output Parameter: 8047 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8048 8049 Level: developer 8050 8051 Note: 8052 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8053 us of the array after it has been restored. If you pass `NULL`, it will 8054 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8055 8056 Fortran Note: 8057 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8058 8059 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8060 @*/ 8061 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8062 { 8063 PetscFunctionBegin; 8064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8065 PetscValidType(mat, 1); 8066 if (ia) PetscAssertPointer(ia, 6); 8067 if (ja) PetscAssertPointer(ja, 7); 8068 if (done) PetscAssertPointer(done, 8); 8069 MatCheckPreallocated(mat, 1); 8070 8071 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8072 else { 8073 if (done) *done = PETSC_TRUE; 8074 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8075 if (n) *n = 0; 8076 if (ia) *ia = NULL; 8077 if (ja) *ja = NULL; 8078 } 8079 PetscFunctionReturn(PETSC_SUCCESS); 8080 } 8081 8082 /*@C 8083 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8084 8085 Collective 8086 8087 Input Parameters: 8088 + mat - the matrix 8089 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8090 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8091 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8092 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8093 always used. 8094 8095 Output Parameters: 8096 + n - size of (possibly compressed) matrix 8097 . ia - the column pointers 8098 . ja - the row indices 8099 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8100 8101 Level: developer 8102 8103 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8104 @*/ 8105 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8106 { 8107 PetscFunctionBegin; 8108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8109 PetscValidType(mat, 1); 8110 if (ia) PetscAssertPointer(ia, 6); 8111 if (ja) PetscAssertPointer(ja, 7); 8112 PetscAssertPointer(done, 8); 8113 MatCheckPreallocated(mat, 1); 8114 8115 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8116 else { 8117 *done = PETSC_TRUE; 8118 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8119 if (n) *n = 0; 8120 if (ia) *ia = NULL; 8121 if (ja) *ja = NULL; 8122 } 8123 PetscFunctionReturn(PETSC_SUCCESS); 8124 } 8125 8126 /*@C 8127 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8128 `MatGetColumnIJ()`. 8129 8130 Collective 8131 8132 Input Parameters: 8133 + mat - the matrix 8134 . ncolors - maximum color value 8135 . n - number of entries in colorarray 8136 - colorarray - array indicating color for each column 8137 8138 Output Parameter: 8139 . iscoloring - coloring generated using colorarray information 8140 8141 Level: developer 8142 8143 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8144 @*/ 8145 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8146 { 8147 PetscFunctionBegin; 8148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8149 PetscValidType(mat, 1); 8150 PetscAssertPointer(colorarray, 4); 8151 PetscAssertPointer(iscoloring, 5); 8152 MatCheckPreallocated(mat, 1); 8153 8154 if (!mat->ops->coloringpatch) { 8155 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8156 } else { 8157 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8158 } 8159 PetscFunctionReturn(PETSC_SUCCESS); 8160 } 8161 8162 /*@ 8163 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8164 8165 Logically Collective 8166 8167 Input Parameter: 8168 . mat - the factored matrix to be reset 8169 8170 Level: developer 8171 8172 Notes: 8173 This routine should be used only with factored matrices formed by in-place 8174 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8175 format). This option can save memory, for example, when solving nonlinear 8176 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8177 ILU(0) preconditioner. 8178 8179 One can specify in-place ILU(0) factorization by calling 8180 .vb 8181 PCType(pc,PCILU); 8182 PCFactorSeUseInPlace(pc); 8183 .ve 8184 or by using the options -pc_type ilu -pc_factor_in_place 8185 8186 In-place factorization ILU(0) can also be used as a local 8187 solver for the blocks within the block Jacobi or additive Schwarz 8188 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8189 for details on setting local solver options. 8190 8191 Most users should employ the `KSP` interface for linear solvers 8192 instead of working directly with matrix algebra routines such as this. 8193 See, e.g., `KSPCreate()`. 8194 8195 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8196 @*/ 8197 PetscErrorCode MatSetUnfactored(Mat mat) 8198 { 8199 PetscFunctionBegin; 8200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8201 PetscValidType(mat, 1); 8202 MatCheckPreallocated(mat, 1); 8203 mat->factortype = MAT_FACTOR_NONE; 8204 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8205 PetscUseTypeMethod(mat, setunfactored); 8206 PetscFunctionReturn(PETSC_SUCCESS); 8207 } 8208 8209 /*MC 8210 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8211 8212 Synopsis: 8213 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8214 8215 Not Collective 8216 8217 Input Parameter: 8218 . x - matrix 8219 8220 Output Parameters: 8221 + xx_v - the Fortran pointer to the array 8222 - ierr - error code 8223 8224 Example of Usage: 8225 .vb 8226 PetscScalar, pointer xx_v(:,:) 8227 .... 8228 call MatDenseGetArrayF90(x,xx_v,ierr) 8229 a = xx_v(3) 8230 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8231 .ve 8232 8233 Level: advanced 8234 8235 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8236 M*/ 8237 8238 /*MC 8239 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8240 accessed with `MatDenseGetArrayF90()`. 8241 8242 Synopsis: 8243 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8244 8245 Not Collective 8246 8247 Input Parameters: 8248 + x - matrix 8249 - xx_v - the Fortran90 pointer to the array 8250 8251 Output Parameter: 8252 . ierr - error code 8253 8254 Example of Usage: 8255 .vb 8256 PetscScalar, pointer xx_v(:,:) 8257 .... 8258 call MatDenseGetArrayF90(x,xx_v,ierr) 8259 a = xx_v(3) 8260 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8261 .ve 8262 8263 Level: advanced 8264 8265 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8266 M*/ 8267 8268 /*MC 8269 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8270 8271 Synopsis: 8272 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8273 8274 Not Collective 8275 8276 Input Parameter: 8277 . x - matrix 8278 8279 Output Parameters: 8280 + xx_v - the Fortran pointer to the array 8281 - ierr - error code 8282 8283 Example of Usage: 8284 .vb 8285 PetscScalar, pointer xx_v(:) 8286 .... 8287 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8288 a = xx_v(3) 8289 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8290 .ve 8291 8292 Level: advanced 8293 8294 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8295 M*/ 8296 8297 /*MC 8298 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8299 accessed with `MatSeqAIJGetArrayF90()`. 8300 8301 Synopsis: 8302 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8303 8304 Not Collective 8305 8306 Input Parameters: 8307 + x - matrix 8308 - xx_v - the Fortran90 pointer to the array 8309 8310 Output Parameter: 8311 . ierr - error code 8312 8313 Example of Usage: 8314 .vb 8315 PetscScalar, pointer xx_v(:) 8316 .... 8317 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8318 a = xx_v(3) 8319 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8320 .ve 8321 8322 Level: advanced 8323 8324 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8325 M*/ 8326 8327 /*@ 8328 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8329 as the original matrix. 8330 8331 Collective 8332 8333 Input Parameters: 8334 + mat - the original matrix 8335 . isrow - parallel `IS` containing the rows this processor should obtain 8336 . 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. 8337 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8338 8339 Output Parameter: 8340 . newmat - the new submatrix, of the same type as the original matrix 8341 8342 Level: advanced 8343 8344 Notes: 8345 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8346 8347 Some matrix types place restrictions on the row and column indices, such 8348 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; 8349 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8350 8351 The index sets may not have duplicate entries. 8352 8353 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8354 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8355 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8356 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8357 you are finished using it. 8358 8359 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8360 the input matrix. 8361 8362 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8363 8364 Example usage: 8365 Consider the following 8x8 matrix with 34 non-zero values, that is 8366 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8367 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8368 as follows 8369 .vb 8370 1 2 0 | 0 3 0 | 0 4 8371 Proc0 0 5 6 | 7 0 0 | 8 0 8372 9 0 10 | 11 0 0 | 12 0 8373 ------------------------------------- 8374 13 0 14 | 15 16 17 | 0 0 8375 Proc1 0 18 0 | 19 20 21 | 0 0 8376 0 0 0 | 22 23 0 | 24 0 8377 ------------------------------------- 8378 Proc2 25 26 27 | 0 0 28 | 29 0 8379 30 0 0 | 31 32 33 | 0 34 8380 .ve 8381 8382 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8383 8384 .vb 8385 2 0 | 0 3 0 | 0 8386 Proc0 5 6 | 7 0 0 | 8 8387 ------------------------------- 8388 Proc1 18 0 | 19 20 21 | 0 8389 ------------------------------- 8390 Proc2 26 27 | 0 0 28 | 29 8391 0 0 | 31 32 33 | 0 8392 .ve 8393 8394 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8395 @*/ 8396 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8397 { 8398 PetscMPIInt size; 8399 Mat *local; 8400 IS iscoltmp; 8401 PetscBool flg; 8402 8403 PetscFunctionBegin; 8404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8405 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8406 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8407 PetscAssertPointer(newmat, 5); 8408 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8409 PetscValidType(mat, 1); 8410 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8411 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8412 8413 MatCheckPreallocated(mat, 1); 8414 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8415 8416 if (!iscol || isrow == iscol) { 8417 PetscBool stride; 8418 PetscMPIInt grabentirematrix = 0, grab; 8419 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8420 if (stride) { 8421 PetscInt first, step, n, rstart, rend; 8422 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8423 if (step == 1) { 8424 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8425 if (rstart == first) { 8426 PetscCall(ISGetLocalSize(isrow, &n)); 8427 if (n == rend - rstart) grabentirematrix = 1; 8428 } 8429 } 8430 } 8431 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8432 if (grab) { 8433 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8434 if (cll == MAT_INITIAL_MATRIX) { 8435 *newmat = mat; 8436 PetscCall(PetscObjectReference((PetscObject)mat)); 8437 } 8438 PetscFunctionReturn(PETSC_SUCCESS); 8439 } 8440 } 8441 8442 if (!iscol) { 8443 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8444 } else { 8445 iscoltmp = iscol; 8446 } 8447 8448 /* if original matrix is on just one processor then use submatrix generated */ 8449 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8450 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8451 goto setproperties; 8452 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8453 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8454 *newmat = *local; 8455 PetscCall(PetscFree(local)); 8456 goto setproperties; 8457 } else if (!mat->ops->createsubmatrix) { 8458 /* Create a new matrix type that implements the operation using the full matrix */ 8459 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8460 switch (cll) { 8461 case MAT_INITIAL_MATRIX: 8462 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8463 break; 8464 case MAT_REUSE_MATRIX: 8465 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8466 break; 8467 default: 8468 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8469 } 8470 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8471 goto setproperties; 8472 } 8473 8474 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8475 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8476 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8477 8478 setproperties: 8479 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8480 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8481 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8482 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8483 PetscFunctionReturn(PETSC_SUCCESS); 8484 } 8485 8486 /*@ 8487 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8488 8489 Not Collective 8490 8491 Input Parameters: 8492 + A - the matrix we wish to propagate options from 8493 - B - the matrix we wish to propagate options to 8494 8495 Level: beginner 8496 8497 Note: 8498 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8499 8500 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8501 @*/ 8502 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8503 { 8504 PetscFunctionBegin; 8505 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8506 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8507 B->symmetry_eternal = A->symmetry_eternal; 8508 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8509 B->symmetric = A->symmetric; 8510 B->structurally_symmetric = A->structurally_symmetric; 8511 B->spd = A->spd; 8512 B->hermitian = A->hermitian; 8513 PetscFunctionReturn(PETSC_SUCCESS); 8514 } 8515 8516 /*@ 8517 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8518 used during the assembly process to store values that belong to 8519 other processors. 8520 8521 Not Collective 8522 8523 Input Parameters: 8524 + mat - the matrix 8525 . size - the initial size of the stash. 8526 - bsize - the initial size of the block-stash(if used). 8527 8528 Options Database Keys: 8529 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8530 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8531 8532 Level: intermediate 8533 8534 Notes: 8535 The block-stash is used for values set with `MatSetValuesBlocked()` while 8536 the stash is used for values set with `MatSetValues()` 8537 8538 Run with the option -info and look for output of the form 8539 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8540 to determine the appropriate value, MM, to use for size and 8541 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8542 to determine the value, BMM to use for bsize 8543 8544 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8545 @*/ 8546 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8547 { 8548 PetscFunctionBegin; 8549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8550 PetscValidType(mat, 1); 8551 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8552 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8553 PetscFunctionReturn(PETSC_SUCCESS); 8554 } 8555 8556 /*@ 8557 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8558 the matrix 8559 8560 Neighbor-wise Collective 8561 8562 Input Parameters: 8563 + A - the matrix 8564 . x - the vector to be multiplied by the interpolation operator 8565 - y - the vector to be added to the result 8566 8567 Output Parameter: 8568 . w - the resulting vector 8569 8570 Level: intermediate 8571 8572 Notes: 8573 `w` may be the same vector as `y`. 8574 8575 This allows one to use either the restriction or interpolation (its transpose) 8576 matrix to do the interpolation 8577 8578 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8579 @*/ 8580 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8581 { 8582 PetscInt M, N, Ny; 8583 8584 PetscFunctionBegin; 8585 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8586 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8587 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8588 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8589 PetscCall(MatGetSize(A, &M, &N)); 8590 PetscCall(VecGetSize(y, &Ny)); 8591 if (M == Ny) { 8592 PetscCall(MatMultAdd(A, x, y, w)); 8593 } else { 8594 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8595 } 8596 PetscFunctionReturn(PETSC_SUCCESS); 8597 } 8598 8599 /*@ 8600 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8601 the matrix 8602 8603 Neighbor-wise Collective 8604 8605 Input Parameters: 8606 + A - the matrix 8607 - x - the vector to be interpolated 8608 8609 Output Parameter: 8610 . y - the resulting vector 8611 8612 Level: intermediate 8613 8614 Note: 8615 This allows one to use either the restriction or interpolation (its transpose) 8616 matrix to do the interpolation 8617 8618 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8619 @*/ 8620 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8621 { 8622 PetscInt M, N, Ny; 8623 8624 PetscFunctionBegin; 8625 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8626 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8627 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8628 PetscCall(MatGetSize(A, &M, &N)); 8629 PetscCall(VecGetSize(y, &Ny)); 8630 if (M == Ny) { 8631 PetscCall(MatMult(A, x, y)); 8632 } else { 8633 PetscCall(MatMultTranspose(A, x, y)); 8634 } 8635 PetscFunctionReturn(PETSC_SUCCESS); 8636 } 8637 8638 /*@ 8639 MatRestrict - $y = A*x$ or $A^T*x$ 8640 8641 Neighbor-wise Collective 8642 8643 Input Parameters: 8644 + A - the matrix 8645 - x - the vector to be restricted 8646 8647 Output Parameter: 8648 . y - the resulting vector 8649 8650 Level: intermediate 8651 8652 Note: 8653 This allows one to use either the restriction or interpolation (its transpose) 8654 matrix to do the restriction 8655 8656 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8657 @*/ 8658 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8659 { 8660 PetscInt M, N, Ny; 8661 8662 PetscFunctionBegin; 8663 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8664 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8665 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8666 PetscCall(MatGetSize(A, &M, &N)); 8667 PetscCall(VecGetSize(y, &Ny)); 8668 if (M == Ny) { 8669 PetscCall(MatMult(A, x, y)); 8670 } else { 8671 PetscCall(MatMultTranspose(A, x, y)); 8672 } 8673 PetscFunctionReturn(PETSC_SUCCESS); 8674 } 8675 8676 /*@ 8677 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8678 8679 Neighbor-wise Collective 8680 8681 Input Parameters: 8682 + A - the matrix 8683 . x - the input dense matrix to be multiplied 8684 - w - the input dense matrix to be added to the result 8685 8686 Output Parameter: 8687 . y - the output dense matrix 8688 8689 Level: intermediate 8690 8691 Note: 8692 This allows one to use either the restriction or interpolation (its transpose) 8693 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8694 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8695 8696 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8697 @*/ 8698 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8699 { 8700 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8701 PetscBool trans = PETSC_TRUE; 8702 MatReuse reuse = MAT_INITIAL_MATRIX; 8703 8704 PetscFunctionBegin; 8705 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8706 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8707 PetscValidType(x, 2); 8708 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8709 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8710 PetscCall(MatGetSize(A, &M, &N)); 8711 PetscCall(MatGetSize(x, &Mx, &Nx)); 8712 if (N == Mx) trans = PETSC_FALSE; 8713 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); 8714 Mo = trans ? N : M; 8715 if (*y) { 8716 PetscCall(MatGetSize(*y, &My, &Ny)); 8717 if (Mo == My && Nx == Ny) { 8718 reuse = MAT_REUSE_MATRIX; 8719 } else { 8720 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); 8721 PetscCall(MatDestroy(y)); 8722 } 8723 } 8724 8725 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8726 PetscBool flg; 8727 8728 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8729 if (w) { 8730 PetscInt My, Ny, Mw, Nw; 8731 8732 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8733 PetscCall(MatGetSize(*y, &My, &Ny)); 8734 PetscCall(MatGetSize(w, &Mw, &Nw)); 8735 if (!flg || My != Mw || Ny != Nw) w = NULL; 8736 } 8737 if (!w) { 8738 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8739 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8740 PetscCall(PetscObjectDereference((PetscObject)w)); 8741 } else { 8742 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8743 } 8744 } 8745 if (!trans) { 8746 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8747 } else { 8748 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8749 } 8750 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8751 PetscFunctionReturn(PETSC_SUCCESS); 8752 } 8753 8754 /*@ 8755 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8756 8757 Neighbor-wise Collective 8758 8759 Input Parameters: 8760 + A - the matrix 8761 - x - the input dense matrix 8762 8763 Output Parameter: 8764 . y - the output dense matrix 8765 8766 Level: intermediate 8767 8768 Note: 8769 This allows one to use either the restriction or interpolation (its transpose) 8770 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8771 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8772 8773 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8774 @*/ 8775 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8776 { 8777 PetscFunctionBegin; 8778 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8779 PetscFunctionReturn(PETSC_SUCCESS); 8780 } 8781 8782 /*@ 8783 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8784 8785 Neighbor-wise Collective 8786 8787 Input Parameters: 8788 + A - the matrix 8789 - x - the input dense matrix 8790 8791 Output Parameter: 8792 . y - the output dense matrix 8793 8794 Level: intermediate 8795 8796 Note: 8797 This allows one to use either the restriction or interpolation (its transpose) 8798 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8799 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8800 8801 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8802 @*/ 8803 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8804 { 8805 PetscFunctionBegin; 8806 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8807 PetscFunctionReturn(PETSC_SUCCESS); 8808 } 8809 8810 /*@ 8811 MatGetNullSpace - retrieves the null space of a matrix. 8812 8813 Logically Collective 8814 8815 Input Parameters: 8816 + mat - the matrix 8817 - nullsp - the null space object 8818 8819 Level: developer 8820 8821 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8822 @*/ 8823 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8824 { 8825 PetscFunctionBegin; 8826 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8827 PetscAssertPointer(nullsp, 2); 8828 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8829 PetscFunctionReturn(PETSC_SUCCESS); 8830 } 8831 8832 /*@ 8833 MatSetNullSpace - attaches a null space to a matrix. 8834 8835 Logically Collective 8836 8837 Input Parameters: 8838 + mat - the matrix 8839 - nullsp - the null space object 8840 8841 Level: advanced 8842 8843 Notes: 8844 This null space is used by the `KSP` linear solvers to solve singular systems. 8845 8846 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` 8847 8848 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 8849 to zero but the linear system will still be solved in a least squares sense. 8850 8851 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8852 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)$. 8853 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 8854 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 8855 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$). 8856 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8857 8858 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8859 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8860 routine also automatically calls `MatSetTransposeNullSpace()`. 8861 8862 The user should call `MatNullSpaceDestroy()`. 8863 8864 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8865 `KSPSetPCSide()` 8866 @*/ 8867 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8868 { 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8871 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8872 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8873 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8874 mat->nullsp = nullsp; 8875 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8876 PetscFunctionReturn(PETSC_SUCCESS); 8877 } 8878 8879 /*@ 8880 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + mat - the matrix 8886 - nullsp - the null space object 8887 8888 Level: developer 8889 8890 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8891 @*/ 8892 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8893 { 8894 PetscFunctionBegin; 8895 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8896 PetscValidType(mat, 1); 8897 PetscAssertPointer(nullsp, 2); 8898 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8899 PetscFunctionReturn(PETSC_SUCCESS); 8900 } 8901 8902 /*@ 8903 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8904 8905 Logically Collective 8906 8907 Input Parameters: 8908 + mat - the matrix 8909 - nullsp - the null space object 8910 8911 Level: advanced 8912 8913 Notes: 8914 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8915 8916 See `MatSetNullSpace()` 8917 8918 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8919 @*/ 8920 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8921 { 8922 PetscFunctionBegin; 8923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8924 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8925 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8926 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8927 mat->transnullsp = nullsp; 8928 PetscFunctionReturn(PETSC_SUCCESS); 8929 } 8930 8931 /*@ 8932 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8933 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8934 8935 Logically Collective 8936 8937 Input Parameters: 8938 + mat - the matrix 8939 - nullsp - the null space object 8940 8941 Level: advanced 8942 8943 Notes: 8944 Overwrites any previous near null space that may have been attached 8945 8946 You can remove the null space by calling this routine with an `nullsp` of `NULL` 8947 8948 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8949 @*/ 8950 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8951 { 8952 PetscFunctionBegin; 8953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8954 PetscValidType(mat, 1); 8955 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8956 MatCheckPreallocated(mat, 1); 8957 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8958 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8959 mat->nearnullsp = nullsp; 8960 PetscFunctionReturn(PETSC_SUCCESS); 8961 } 8962 8963 /*@ 8964 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8965 8966 Not Collective 8967 8968 Input Parameter: 8969 . mat - the matrix 8970 8971 Output Parameter: 8972 . nullsp - the null space object, `NULL` if not set 8973 8974 Level: advanced 8975 8976 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8977 @*/ 8978 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8979 { 8980 PetscFunctionBegin; 8981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8982 PetscValidType(mat, 1); 8983 PetscAssertPointer(nullsp, 2); 8984 MatCheckPreallocated(mat, 1); 8985 *nullsp = mat->nearnullsp; 8986 PetscFunctionReturn(PETSC_SUCCESS); 8987 } 8988 8989 /*@C 8990 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8991 8992 Collective 8993 8994 Input Parameters: 8995 + mat - the matrix 8996 . row - row/column permutation 8997 - info - information on desired factorization process 8998 8999 Level: developer 9000 9001 Notes: 9002 Probably really in-place only when level of fill is zero, otherwise allocates 9003 new space to store factored matrix and deletes previous memory. 9004 9005 Most users should employ the `KSP` interface for linear solvers 9006 instead of working directly with matrix algebra routines such as this. 9007 See, e.g., `KSPCreate()`. 9008 9009 Developer Note: 9010 The Fortran interface is not autogenerated as the 9011 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9012 9013 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9014 @*/ 9015 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9016 { 9017 PetscFunctionBegin; 9018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9019 PetscValidType(mat, 1); 9020 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9021 PetscAssertPointer(info, 3); 9022 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9023 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9024 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9025 MatCheckPreallocated(mat, 1); 9026 PetscUseTypeMethod(mat, iccfactor, row, info); 9027 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9028 PetscFunctionReturn(PETSC_SUCCESS); 9029 } 9030 9031 /*@ 9032 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9033 ghosted ones. 9034 9035 Not Collective 9036 9037 Input Parameters: 9038 + mat - the matrix 9039 - diag - the diagonal values, including ghost ones 9040 9041 Level: developer 9042 9043 Notes: 9044 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9045 9046 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9047 9048 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9049 @*/ 9050 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9051 { 9052 PetscMPIInt size; 9053 9054 PetscFunctionBegin; 9055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9056 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9057 PetscValidType(mat, 1); 9058 9059 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9060 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9061 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9062 if (size == 1) { 9063 PetscInt n, m; 9064 PetscCall(VecGetSize(diag, &n)); 9065 PetscCall(MatGetSize(mat, NULL, &m)); 9066 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9067 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9068 } else { 9069 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9070 } 9071 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9072 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9073 PetscFunctionReturn(PETSC_SUCCESS); 9074 } 9075 9076 /*@ 9077 MatGetInertia - Gets the inertia from a factored matrix 9078 9079 Collective 9080 9081 Input Parameter: 9082 . mat - the matrix 9083 9084 Output Parameters: 9085 + nneg - number of negative eigenvalues 9086 . nzero - number of zero eigenvalues 9087 - npos - number of positive eigenvalues 9088 9089 Level: advanced 9090 9091 Note: 9092 Matrix must have been factored by `MatCholeskyFactor()` 9093 9094 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9095 @*/ 9096 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9097 { 9098 PetscFunctionBegin; 9099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9100 PetscValidType(mat, 1); 9101 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9102 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9103 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9104 PetscFunctionReturn(PETSC_SUCCESS); 9105 } 9106 9107 /*@C 9108 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9109 9110 Neighbor-wise Collective 9111 9112 Input Parameters: 9113 + mat - the factored matrix obtained with `MatGetFactor()` 9114 - b - the right-hand-side vectors 9115 9116 Output Parameter: 9117 . x - the result vectors 9118 9119 Level: developer 9120 9121 Note: 9122 The vectors `b` and `x` cannot be the same. I.e., one cannot 9123 call `MatSolves`(A,x,x). 9124 9125 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9126 @*/ 9127 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9128 { 9129 PetscFunctionBegin; 9130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9131 PetscValidType(mat, 1); 9132 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9133 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9134 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9135 9136 MatCheckPreallocated(mat, 1); 9137 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9138 PetscUseTypeMethod(mat, solves, b, x); 9139 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9140 PetscFunctionReturn(PETSC_SUCCESS); 9141 } 9142 9143 /*@ 9144 MatIsSymmetric - Test whether a matrix is symmetric 9145 9146 Collective 9147 9148 Input Parameters: 9149 + A - the matrix to test 9150 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9151 9152 Output Parameter: 9153 . flg - the result 9154 9155 Level: intermediate 9156 9157 Notes: 9158 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9159 9160 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9161 9162 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9163 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9164 9165 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9166 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9167 @*/ 9168 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9169 { 9170 PetscFunctionBegin; 9171 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9172 PetscAssertPointer(flg, 3); 9173 9174 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9175 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9176 else { 9177 PetscUseTypeMethod(A, issymmetric, tol, flg); 9178 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9179 } 9180 PetscFunctionReturn(PETSC_SUCCESS); 9181 } 9182 9183 /*@ 9184 MatIsHermitian - Test whether a matrix is Hermitian 9185 9186 Collective 9187 9188 Input Parameters: 9189 + A - the matrix to test 9190 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9191 9192 Output Parameter: 9193 . flg - the result 9194 9195 Level: intermediate 9196 9197 Notes: 9198 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9199 9200 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9201 9202 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9203 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9204 9205 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9206 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9207 @*/ 9208 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9209 { 9210 PetscFunctionBegin; 9211 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9212 PetscAssertPointer(flg, 3); 9213 9214 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9215 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9216 else { 9217 PetscUseTypeMethod(A, ishermitian, tol, flg); 9218 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9219 } 9220 PetscFunctionReturn(PETSC_SUCCESS); 9221 } 9222 9223 /*@ 9224 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9225 9226 Not Collective 9227 9228 Input Parameter: 9229 . A - the matrix to check 9230 9231 Output Parameters: 9232 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9233 - flg - the result (only valid if set is `PETSC_TRUE`) 9234 9235 Level: advanced 9236 9237 Notes: 9238 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9239 if you want it explicitly checked 9240 9241 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9242 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9243 9244 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9245 @*/ 9246 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9247 { 9248 PetscFunctionBegin; 9249 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9250 PetscAssertPointer(set, 2); 9251 PetscAssertPointer(flg, 3); 9252 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9253 *set = PETSC_TRUE; 9254 *flg = PetscBool3ToBool(A->symmetric); 9255 } else { 9256 *set = PETSC_FALSE; 9257 } 9258 PetscFunctionReturn(PETSC_SUCCESS); 9259 } 9260 9261 /*@ 9262 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9263 9264 Not Collective 9265 9266 Input Parameter: 9267 . A - the matrix to check 9268 9269 Output Parameters: 9270 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9271 - flg - the result (only valid if set is `PETSC_TRUE`) 9272 9273 Level: advanced 9274 9275 Notes: 9276 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9277 9278 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9279 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9280 9281 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9282 @*/ 9283 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9284 { 9285 PetscFunctionBegin; 9286 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9287 PetscAssertPointer(set, 2); 9288 PetscAssertPointer(flg, 3); 9289 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9290 *set = PETSC_TRUE; 9291 *flg = PetscBool3ToBool(A->spd); 9292 } else { 9293 *set = PETSC_FALSE; 9294 } 9295 PetscFunctionReturn(PETSC_SUCCESS); 9296 } 9297 9298 /*@ 9299 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9300 9301 Not Collective 9302 9303 Input Parameter: 9304 . A - the matrix to check 9305 9306 Output Parameters: 9307 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9308 - flg - the result (only valid if set is `PETSC_TRUE`) 9309 9310 Level: advanced 9311 9312 Notes: 9313 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9314 if you want it explicitly checked 9315 9316 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9317 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9318 9319 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9320 @*/ 9321 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9322 { 9323 PetscFunctionBegin; 9324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9325 PetscAssertPointer(set, 2); 9326 PetscAssertPointer(flg, 3); 9327 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9328 *set = PETSC_TRUE; 9329 *flg = PetscBool3ToBool(A->hermitian); 9330 } else { 9331 *set = PETSC_FALSE; 9332 } 9333 PetscFunctionReturn(PETSC_SUCCESS); 9334 } 9335 9336 /*@ 9337 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9338 9339 Collective 9340 9341 Input Parameter: 9342 . A - the matrix to test 9343 9344 Output Parameter: 9345 . flg - the result 9346 9347 Level: intermediate 9348 9349 Notes: 9350 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9351 9352 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 9353 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9354 9355 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9356 @*/ 9357 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9358 { 9359 PetscFunctionBegin; 9360 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9361 PetscAssertPointer(flg, 2); 9362 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9363 *flg = PetscBool3ToBool(A->structurally_symmetric); 9364 } else { 9365 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9366 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9367 } 9368 PetscFunctionReturn(PETSC_SUCCESS); 9369 } 9370 9371 /*@ 9372 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9373 9374 Not Collective 9375 9376 Input Parameter: 9377 . A - the matrix to check 9378 9379 Output Parameters: 9380 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9381 - flg - the result (only valid if set is PETSC_TRUE) 9382 9383 Level: advanced 9384 9385 Notes: 9386 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 9387 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9388 9389 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9390 9391 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9392 @*/ 9393 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9394 { 9395 PetscFunctionBegin; 9396 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9397 PetscAssertPointer(set, 2); 9398 PetscAssertPointer(flg, 3); 9399 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9400 *set = PETSC_TRUE; 9401 *flg = PetscBool3ToBool(A->structurally_symmetric); 9402 } else { 9403 *set = PETSC_FALSE; 9404 } 9405 PetscFunctionReturn(PETSC_SUCCESS); 9406 } 9407 9408 /*@ 9409 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9410 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9411 9412 Not Collective 9413 9414 Input Parameter: 9415 . mat - the matrix 9416 9417 Output Parameters: 9418 + nstash - the size of the stash 9419 . reallocs - the number of additional mallocs incurred. 9420 . bnstash - the size of the block stash 9421 - breallocs - the number of additional mallocs incurred.in the block stash 9422 9423 Level: advanced 9424 9425 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9426 @*/ 9427 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9428 { 9429 PetscFunctionBegin; 9430 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9431 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9432 PetscFunctionReturn(PETSC_SUCCESS); 9433 } 9434 9435 /*@C 9436 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9437 parallel layout, `PetscLayout` for rows and columns 9438 9439 Collective 9440 9441 Input Parameter: 9442 . mat - the matrix 9443 9444 Output Parameters: 9445 + right - (optional) vector that the matrix can be multiplied against 9446 - left - (optional) vector that the matrix vector product can be stored in 9447 9448 Level: advanced 9449 9450 Notes: 9451 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()`. 9452 9453 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9454 9455 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9456 @*/ 9457 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9458 { 9459 PetscFunctionBegin; 9460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9461 PetscValidType(mat, 1); 9462 if (mat->ops->getvecs) { 9463 PetscUseTypeMethod(mat, getvecs, right, left); 9464 } else { 9465 if (right) { 9466 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9467 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9468 PetscCall(VecSetType(*right, mat->defaultvectype)); 9469 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9470 if (mat->boundtocpu && mat->bindingpropagates) { 9471 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9472 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9473 } 9474 #endif 9475 } 9476 if (left) { 9477 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9478 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9479 PetscCall(VecSetType(*left, mat->defaultvectype)); 9480 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9481 if (mat->boundtocpu && mat->bindingpropagates) { 9482 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9483 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9484 } 9485 #endif 9486 } 9487 } 9488 PetscFunctionReturn(PETSC_SUCCESS); 9489 } 9490 9491 /*@C 9492 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9493 with default values. 9494 9495 Not Collective 9496 9497 Input Parameter: 9498 . info - the `MatFactorInfo` data structure 9499 9500 Level: developer 9501 9502 Notes: 9503 The solvers are generally used through the `KSP` and `PC` objects, for example 9504 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9505 9506 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9507 9508 Developer Note: 9509 The Fortran interface is not autogenerated as the 9510 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9511 9512 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9513 @*/ 9514 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9515 { 9516 PetscFunctionBegin; 9517 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9518 PetscFunctionReturn(PETSC_SUCCESS); 9519 } 9520 9521 /*@ 9522 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9523 9524 Collective 9525 9526 Input Parameters: 9527 + mat - the factored matrix 9528 - is - the index set defining the Schur indices (0-based) 9529 9530 Level: advanced 9531 9532 Notes: 9533 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9534 9535 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9536 9537 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9538 9539 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9540 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9541 @*/ 9542 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9543 { 9544 PetscErrorCode (*f)(Mat, IS); 9545 9546 PetscFunctionBegin; 9547 PetscValidType(mat, 1); 9548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9549 PetscValidType(is, 2); 9550 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9551 PetscCheckSameComm(mat, 1, is, 2); 9552 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9553 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9554 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9555 PetscCall(MatDestroy(&mat->schur)); 9556 PetscCall((*f)(mat, is)); 9557 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9558 PetscFunctionReturn(PETSC_SUCCESS); 9559 } 9560 9561 /*@ 9562 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9563 9564 Logically Collective 9565 9566 Input Parameters: 9567 + F - the factored matrix obtained by calling `MatGetFactor()` 9568 . S - location where to return the Schur complement, can be `NULL` 9569 - status - the status of the Schur complement matrix, can be `NULL` 9570 9571 Level: advanced 9572 9573 Notes: 9574 You must call `MatFactorSetSchurIS()` before calling this routine. 9575 9576 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9577 9578 The routine provides a copy of the Schur matrix stored within the solver data structures. 9579 The caller must destroy the object when it is no longer needed. 9580 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9581 9582 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) 9583 9584 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9585 9586 Developer Note: 9587 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9588 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9589 9590 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9591 @*/ 9592 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9593 { 9594 PetscFunctionBegin; 9595 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9596 if (S) PetscAssertPointer(S, 2); 9597 if (status) PetscAssertPointer(status, 3); 9598 if (S) { 9599 PetscErrorCode (*f)(Mat, Mat *); 9600 9601 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9602 if (f) { 9603 PetscCall((*f)(F, S)); 9604 } else { 9605 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9606 } 9607 } 9608 if (status) *status = F->schur_status; 9609 PetscFunctionReturn(PETSC_SUCCESS); 9610 } 9611 9612 /*@ 9613 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9614 9615 Logically Collective 9616 9617 Input Parameters: 9618 + F - the factored matrix obtained by calling `MatGetFactor()` 9619 . S - location where to return the Schur complement, can be `NULL` 9620 - status - the status of the Schur complement matrix, can be `NULL` 9621 9622 Level: advanced 9623 9624 Notes: 9625 You must call `MatFactorSetSchurIS()` before calling this routine. 9626 9627 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9628 9629 The routine returns a the Schur Complement stored within the data structures of the solver. 9630 9631 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9632 9633 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9634 9635 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9636 9637 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9638 9639 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9640 @*/ 9641 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9642 { 9643 PetscFunctionBegin; 9644 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9645 if (S) { 9646 PetscAssertPointer(S, 2); 9647 *S = F->schur; 9648 } 9649 if (status) { 9650 PetscAssertPointer(status, 3); 9651 *status = F->schur_status; 9652 } 9653 PetscFunctionReturn(PETSC_SUCCESS); 9654 } 9655 9656 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9657 { 9658 Mat S = F->schur; 9659 9660 PetscFunctionBegin; 9661 switch (F->schur_status) { 9662 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9663 case MAT_FACTOR_SCHUR_INVERTED: 9664 if (S) { 9665 S->ops->solve = NULL; 9666 S->ops->matsolve = NULL; 9667 S->ops->solvetranspose = NULL; 9668 S->ops->matsolvetranspose = NULL; 9669 S->ops->solveadd = NULL; 9670 S->ops->solvetransposeadd = NULL; 9671 S->factortype = MAT_FACTOR_NONE; 9672 PetscCall(PetscFree(S->solvertype)); 9673 } 9674 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9675 break; 9676 default: 9677 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9678 } 9679 PetscFunctionReturn(PETSC_SUCCESS); 9680 } 9681 9682 /*@ 9683 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9684 9685 Logically Collective 9686 9687 Input Parameters: 9688 + F - the factored matrix obtained by calling `MatGetFactor()` 9689 . S - location where the Schur complement is stored 9690 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9691 9692 Level: advanced 9693 9694 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9695 @*/ 9696 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9697 { 9698 PetscFunctionBegin; 9699 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9700 if (S) { 9701 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9702 *S = NULL; 9703 } 9704 F->schur_status = status; 9705 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9706 PetscFunctionReturn(PETSC_SUCCESS); 9707 } 9708 9709 /*@ 9710 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9711 9712 Logically Collective 9713 9714 Input Parameters: 9715 + F - the factored matrix obtained by calling `MatGetFactor()` 9716 . rhs - location where the right hand side of the Schur complement system is stored 9717 - sol - location where the solution of the Schur complement system has to be returned 9718 9719 Level: advanced 9720 9721 Notes: 9722 The sizes of the vectors should match the size of the Schur complement 9723 9724 Must be called after `MatFactorSetSchurIS()` 9725 9726 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9727 @*/ 9728 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9729 { 9730 PetscFunctionBegin; 9731 PetscValidType(F, 1); 9732 PetscValidType(rhs, 2); 9733 PetscValidType(sol, 3); 9734 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9735 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9736 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9737 PetscCheckSameComm(F, 1, rhs, 2); 9738 PetscCheckSameComm(F, 1, sol, 3); 9739 PetscCall(MatFactorFactorizeSchurComplement(F)); 9740 switch (F->schur_status) { 9741 case MAT_FACTOR_SCHUR_FACTORED: 9742 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9743 break; 9744 case MAT_FACTOR_SCHUR_INVERTED: 9745 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9746 break; 9747 default: 9748 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9749 } 9750 PetscFunctionReturn(PETSC_SUCCESS); 9751 } 9752 9753 /*@ 9754 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9755 9756 Logically Collective 9757 9758 Input Parameters: 9759 + F - the factored matrix obtained by calling `MatGetFactor()` 9760 . rhs - location where the right hand side of the Schur complement system is stored 9761 - sol - location where the solution of the Schur complement system has to be returned 9762 9763 Level: advanced 9764 9765 Notes: 9766 The sizes of the vectors should match the size of the Schur complement 9767 9768 Must be called after `MatFactorSetSchurIS()` 9769 9770 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9771 @*/ 9772 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9773 { 9774 PetscFunctionBegin; 9775 PetscValidType(F, 1); 9776 PetscValidType(rhs, 2); 9777 PetscValidType(sol, 3); 9778 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9779 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9780 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9781 PetscCheckSameComm(F, 1, rhs, 2); 9782 PetscCheckSameComm(F, 1, sol, 3); 9783 PetscCall(MatFactorFactorizeSchurComplement(F)); 9784 switch (F->schur_status) { 9785 case MAT_FACTOR_SCHUR_FACTORED: 9786 PetscCall(MatSolve(F->schur, rhs, sol)); 9787 break; 9788 case MAT_FACTOR_SCHUR_INVERTED: 9789 PetscCall(MatMult(F->schur, rhs, sol)); 9790 break; 9791 default: 9792 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9793 } 9794 PetscFunctionReturn(PETSC_SUCCESS); 9795 } 9796 9797 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9798 #if PetscDefined(HAVE_CUDA) 9799 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9800 #endif 9801 9802 /* Schur status updated in the interface */ 9803 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9804 { 9805 Mat S = F->schur; 9806 9807 PetscFunctionBegin; 9808 if (S) { 9809 PetscMPIInt size; 9810 PetscBool isdense, isdensecuda; 9811 9812 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9813 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9814 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9815 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9816 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9817 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9818 if (isdense) { 9819 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9820 } else if (isdensecuda) { 9821 #if defined(PETSC_HAVE_CUDA) 9822 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9823 #endif 9824 } 9825 // HIP?????????????? 9826 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9827 } 9828 PetscFunctionReturn(PETSC_SUCCESS); 9829 } 9830 9831 /*@ 9832 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9833 9834 Logically Collective 9835 9836 Input Parameter: 9837 . F - the factored matrix obtained by calling `MatGetFactor()` 9838 9839 Level: advanced 9840 9841 Notes: 9842 Must be called after `MatFactorSetSchurIS()`. 9843 9844 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9845 9846 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9847 @*/ 9848 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9849 { 9850 PetscFunctionBegin; 9851 PetscValidType(F, 1); 9852 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9853 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9854 PetscCall(MatFactorFactorizeSchurComplement(F)); 9855 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9856 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9857 PetscFunctionReturn(PETSC_SUCCESS); 9858 } 9859 9860 /*@ 9861 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9862 9863 Logically Collective 9864 9865 Input Parameter: 9866 . F - the factored matrix obtained by calling `MatGetFactor()` 9867 9868 Level: advanced 9869 9870 Note: 9871 Must be called after `MatFactorSetSchurIS()` 9872 9873 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9874 @*/ 9875 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9876 { 9877 MatFactorInfo info; 9878 9879 PetscFunctionBegin; 9880 PetscValidType(F, 1); 9881 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9882 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9883 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9884 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9885 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9886 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9887 } else { 9888 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9889 } 9890 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9891 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9892 PetscFunctionReturn(PETSC_SUCCESS); 9893 } 9894 9895 /*@ 9896 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9897 9898 Neighbor-wise Collective 9899 9900 Input Parameters: 9901 + A - the matrix 9902 . P - the projection matrix 9903 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9904 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9905 if the result is a dense matrix this is irrelevant 9906 9907 Output Parameter: 9908 . C - the product matrix 9909 9910 Level: intermediate 9911 9912 Notes: 9913 C will be created and must be destroyed by the user with `MatDestroy()`. 9914 9915 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9916 9917 Developer Note: 9918 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9919 9920 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9921 @*/ 9922 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9923 { 9924 PetscFunctionBegin; 9925 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9926 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9927 9928 if (scall == MAT_INITIAL_MATRIX) { 9929 PetscCall(MatProductCreate(A, P, NULL, C)); 9930 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9931 PetscCall(MatProductSetAlgorithm(*C, "default")); 9932 PetscCall(MatProductSetFill(*C, fill)); 9933 9934 (*C)->product->api_user = PETSC_TRUE; 9935 PetscCall(MatProductSetFromOptions(*C)); 9936 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); 9937 PetscCall(MatProductSymbolic(*C)); 9938 } else { /* scall == MAT_REUSE_MATRIX */ 9939 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9940 } 9941 9942 PetscCall(MatProductNumeric(*C)); 9943 (*C)->symmetric = A->symmetric; 9944 (*C)->spd = A->spd; 9945 PetscFunctionReturn(PETSC_SUCCESS); 9946 } 9947 9948 /*@ 9949 MatRARt - Creates the matrix product $C = R * A * R^T$ 9950 9951 Neighbor-wise Collective 9952 9953 Input Parameters: 9954 + A - the matrix 9955 . R - the projection matrix 9956 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9957 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9958 if the result is a dense matrix this is irrelevant 9959 9960 Output Parameter: 9961 . C - the product matrix 9962 9963 Level: intermediate 9964 9965 Notes: 9966 C will be created and must be destroyed by the user with `MatDestroy()`. 9967 9968 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9969 9970 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9971 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9972 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9973 We recommend using MatPtAP(). 9974 9975 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9976 @*/ 9977 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9978 { 9979 PetscFunctionBegin; 9980 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9981 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9982 9983 if (scall == MAT_INITIAL_MATRIX) { 9984 PetscCall(MatProductCreate(A, R, NULL, C)); 9985 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9986 PetscCall(MatProductSetAlgorithm(*C, "default")); 9987 PetscCall(MatProductSetFill(*C, fill)); 9988 9989 (*C)->product->api_user = PETSC_TRUE; 9990 PetscCall(MatProductSetFromOptions(*C)); 9991 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); 9992 PetscCall(MatProductSymbolic(*C)); 9993 } else { /* scall == MAT_REUSE_MATRIX */ 9994 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9995 } 9996 9997 PetscCall(MatProductNumeric(*C)); 9998 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9999 PetscFunctionReturn(PETSC_SUCCESS); 10000 } 10001 10002 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10003 { 10004 PetscFunctionBegin; 10005 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10006 10007 if (scall == MAT_INITIAL_MATRIX) { 10008 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10009 PetscCall(MatProductCreate(A, B, NULL, C)); 10010 PetscCall(MatProductSetType(*C, ptype)); 10011 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10012 PetscCall(MatProductSetFill(*C, fill)); 10013 10014 (*C)->product->api_user = PETSC_TRUE; 10015 PetscCall(MatProductSetFromOptions(*C)); 10016 PetscCall(MatProductSymbolic(*C)); 10017 } else { /* scall == MAT_REUSE_MATRIX */ 10018 Mat_Product *product = (*C)->product; 10019 PetscBool isdense; 10020 10021 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10022 if (isdense && product && product->type != ptype) { 10023 PetscCall(MatProductClear(*C)); 10024 product = NULL; 10025 } 10026 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10027 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10028 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10029 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10030 product = (*C)->product; 10031 product->fill = fill; 10032 product->api_user = PETSC_TRUE; 10033 product->clear = PETSC_TRUE; 10034 10035 PetscCall(MatProductSetType(*C, ptype)); 10036 PetscCall(MatProductSetFromOptions(*C)); 10037 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); 10038 PetscCall(MatProductSymbolic(*C)); 10039 } else { /* user may change input matrices A or B when REUSE */ 10040 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10041 } 10042 } 10043 PetscCall(MatProductNumeric(*C)); 10044 PetscFunctionReturn(PETSC_SUCCESS); 10045 } 10046 10047 /*@ 10048 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10049 10050 Neighbor-wise Collective 10051 10052 Input Parameters: 10053 + A - the left matrix 10054 . B - the right matrix 10055 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10056 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10057 if the result is a dense matrix this is irrelevant 10058 10059 Output Parameter: 10060 . C - the product matrix 10061 10062 Notes: 10063 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10064 10065 `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 10066 call to this function with `MAT_INITIAL_MATRIX`. 10067 10068 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10069 10070 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`, 10071 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10072 10073 Example of Usage: 10074 .vb 10075 MatProductCreate(A,B,NULL,&C); 10076 MatProductSetType(C,MATPRODUCT_AB); 10077 MatProductSymbolic(C); 10078 MatProductNumeric(C); // compute C=A * B 10079 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10080 MatProductNumeric(C); 10081 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10082 MatProductNumeric(C); 10083 .ve 10084 10085 Level: intermediate 10086 10087 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10088 @*/ 10089 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10090 { 10091 PetscFunctionBegin; 10092 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10093 PetscFunctionReturn(PETSC_SUCCESS); 10094 } 10095 10096 /*@ 10097 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10098 10099 Neighbor-wise Collective 10100 10101 Input Parameters: 10102 + A - the left matrix 10103 . B - the right matrix 10104 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10105 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10106 10107 Output Parameter: 10108 . C - the product matrix 10109 10110 Options Database Key: 10111 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10112 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10113 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10114 10115 Level: intermediate 10116 10117 Notes: 10118 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10119 10120 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10121 10122 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10123 actually needed. 10124 10125 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10126 and for pairs of `MATMPIDENSE` matrices. 10127 10128 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10129 10130 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10131 @*/ 10132 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10133 { 10134 PetscFunctionBegin; 10135 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10136 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10137 PetscFunctionReturn(PETSC_SUCCESS); 10138 } 10139 10140 /*@ 10141 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10142 10143 Neighbor-wise Collective 10144 10145 Input Parameters: 10146 + A - the left matrix 10147 . B - the right matrix 10148 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10149 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10150 10151 Output Parameter: 10152 . C - the product matrix 10153 10154 Level: intermediate 10155 10156 Notes: 10157 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10158 10159 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10160 10161 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10162 10163 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10164 actually needed. 10165 10166 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10167 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10168 10169 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10170 @*/ 10171 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10172 { 10173 PetscFunctionBegin; 10174 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10175 PetscFunctionReturn(PETSC_SUCCESS); 10176 } 10177 10178 /*@ 10179 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10180 10181 Neighbor-wise Collective 10182 10183 Input Parameters: 10184 + A - the left matrix 10185 . B - the middle matrix 10186 . C - the right matrix 10187 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10188 - 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 10189 if the result is a dense matrix this is irrelevant 10190 10191 Output Parameter: 10192 . D - the product matrix 10193 10194 Level: intermediate 10195 10196 Notes: 10197 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10198 10199 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10200 10201 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10202 10203 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10204 actually needed. 10205 10206 If you have many matrices with the same non-zero structure to multiply, you 10207 should use `MAT_REUSE_MATRIX` in all calls but the first 10208 10209 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10210 @*/ 10211 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10212 { 10213 PetscFunctionBegin; 10214 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10215 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10216 10217 if (scall == MAT_INITIAL_MATRIX) { 10218 PetscCall(MatProductCreate(A, B, C, D)); 10219 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10220 PetscCall(MatProductSetAlgorithm(*D, "default")); 10221 PetscCall(MatProductSetFill(*D, fill)); 10222 10223 (*D)->product->api_user = PETSC_TRUE; 10224 PetscCall(MatProductSetFromOptions(*D)); 10225 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, 10226 ((PetscObject)C)->type_name); 10227 PetscCall(MatProductSymbolic(*D)); 10228 } else { /* user may change input matrices when REUSE */ 10229 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10230 } 10231 PetscCall(MatProductNumeric(*D)); 10232 PetscFunctionReturn(PETSC_SUCCESS); 10233 } 10234 10235 /*@ 10236 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10237 10238 Collective 10239 10240 Input Parameters: 10241 + mat - the matrix 10242 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10243 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10244 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10245 10246 Output Parameter: 10247 . matredundant - redundant matrix 10248 10249 Level: advanced 10250 10251 Notes: 10252 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10253 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10254 10255 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10256 calling it. 10257 10258 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10259 10260 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10261 @*/ 10262 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10263 { 10264 MPI_Comm comm; 10265 PetscMPIInt size; 10266 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10267 Mat_Redundant *redund = NULL; 10268 PetscSubcomm psubcomm = NULL; 10269 MPI_Comm subcomm_in = subcomm; 10270 Mat *matseq; 10271 IS isrow, iscol; 10272 PetscBool newsubcomm = PETSC_FALSE; 10273 10274 PetscFunctionBegin; 10275 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10276 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10277 PetscAssertPointer(*matredundant, 5); 10278 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10279 } 10280 10281 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10282 if (size == 1 || nsubcomm == 1) { 10283 if (reuse == MAT_INITIAL_MATRIX) { 10284 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10285 } else { 10286 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"); 10287 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10288 } 10289 PetscFunctionReturn(PETSC_SUCCESS); 10290 } 10291 10292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10294 MatCheckPreallocated(mat, 1); 10295 10296 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10297 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10298 /* create psubcomm, then get subcomm */ 10299 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10300 PetscCallMPI(MPI_Comm_size(comm, &size)); 10301 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10302 10303 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10304 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10305 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10306 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10307 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10308 newsubcomm = PETSC_TRUE; 10309 PetscCall(PetscSubcommDestroy(&psubcomm)); 10310 } 10311 10312 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10313 if (reuse == MAT_INITIAL_MATRIX) { 10314 mloc_sub = PETSC_DECIDE; 10315 nloc_sub = PETSC_DECIDE; 10316 if (bs < 1) { 10317 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10318 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10319 } else { 10320 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10321 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10322 } 10323 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10324 rstart = rend - mloc_sub; 10325 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10326 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10327 PetscCall(ISSetIdentity(iscol)); 10328 } else { /* reuse == MAT_REUSE_MATRIX */ 10329 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"); 10330 /* retrieve subcomm */ 10331 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10332 redund = (*matredundant)->redundant; 10333 isrow = redund->isrow; 10334 iscol = redund->iscol; 10335 matseq = redund->matseq; 10336 } 10337 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10338 10339 /* get matredundant over subcomm */ 10340 if (reuse == MAT_INITIAL_MATRIX) { 10341 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10342 10343 /* create a supporting struct and attach it to C for reuse */ 10344 PetscCall(PetscNew(&redund)); 10345 (*matredundant)->redundant = redund; 10346 redund->isrow = isrow; 10347 redund->iscol = iscol; 10348 redund->matseq = matseq; 10349 if (newsubcomm) { 10350 redund->subcomm = subcomm; 10351 } else { 10352 redund->subcomm = MPI_COMM_NULL; 10353 } 10354 } else { 10355 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10356 } 10357 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10358 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10359 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10360 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10361 } 10362 #endif 10363 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10364 PetscFunctionReturn(PETSC_SUCCESS); 10365 } 10366 10367 /*@C 10368 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10369 a given `Mat`. Each submatrix can span multiple procs. 10370 10371 Collective 10372 10373 Input Parameters: 10374 + mat - the matrix 10375 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10376 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10377 10378 Output Parameter: 10379 . subMat - parallel sub-matrices each spanning a given `subcomm` 10380 10381 Level: advanced 10382 10383 Notes: 10384 The submatrix partition across processors is dictated by `subComm` a 10385 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10386 is not restricted to be grouped with consecutive original MPI processes. 10387 10388 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10389 map directly to the layout of the original matrix [wrt the local 10390 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10391 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10392 the `subMat`. However the offDiagMat looses some columns - and this is 10393 reconstructed with `MatSetValues()` 10394 10395 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10396 10397 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10398 @*/ 10399 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10400 { 10401 PetscMPIInt commsize, subCommSize; 10402 10403 PetscFunctionBegin; 10404 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10405 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10406 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10407 10408 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"); 10409 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10410 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10411 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10412 PetscFunctionReturn(PETSC_SUCCESS); 10413 } 10414 10415 /*@ 10416 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10417 10418 Not Collective 10419 10420 Input Parameters: 10421 + mat - matrix to extract local submatrix from 10422 . isrow - local row indices for submatrix 10423 - iscol - local column indices for submatrix 10424 10425 Output Parameter: 10426 . submat - the submatrix 10427 10428 Level: intermediate 10429 10430 Notes: 10431 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10432 10433 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10434 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10435 10436 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10437 `MatSetValuesBlockedLocal()` will also be implemented. 10438 10439 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10440 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10441 10442 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10443 @*/ 10444 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10445 { 10446 PetscFunctionBegin; 10447 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10448 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10449 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10450 PetscCheckSameComm(isrow, 2, iscol, 3); 10451 PetscAssertPointer(submat, 4); 10452 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10453 10454 if (mat->ops->getlocalsubmatrix) { 10455 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10456 } else { 10457 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10458 } 10459 PetscFunctionReturn(PETSC_SUCCESS); 10460 } 10461 10462 /*@ 10463 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10464 10465 Not Collective 10466 10467 Input Parameters: 10468 + mat - matrix to extract local submatrix from 10469 . isrow - local row indices for submatrix 10470 . iscol - local column indices for submatrix 10471 - submat - the submatrix 10472 10473 Level: intermediate 10474 10475 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10476 @*/ 10477 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10478 { 10479 PetscFunctionBegin; 10480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10481 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10482 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10483 PetscCheckSameComm(isrow, 2, iscol, 3); 10484 PetscAssertPointer(submat, 4); 10485 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10486 10487 if (mat->ops->restorelocalsubmatrix) { 10488 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10489 } else { 10490 PetscCall(MatDestroy(submat)); 10491 } 10492 *submat = NULL; 10493 PetscFunctionReturn(PETSC_SUCCESS); 10494 } 10495 10496 /*@ 10497 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10498 10499 Collective 10500 10501 Input Parameter: 10502 . mat - the matrix 10503 10504 Output Parameter: 10505 . is - if any rows have zero diagonals this contains the list of them 10506 10507 Level: developer 10508 10509 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10510 @*/ 10511 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10512 { 10513 PetscFunctionBegin; 10514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10515 PetscValidType(mat, 1); 10516 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10517 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10518 10519 if (!mat->ops->findzerodiagonals) { 10520 Vec diag; 10521 const PetscScalar *a; 10522 PetscInt *rows; 10523 PetscInt rStart, rEnd, r, nrow = 0; 10524 10525 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10526 PetscCall(MatGetDiagonal(mat, diag)); 10527 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10528 PetscCall(VecGetArrayRead(diag, &a)); 10529 for (r = 0; r < rEnd - rStart; ++r) 10530 if (a[r] == 0.0) ++nrow; 10531 PetscCall(PetscMalloc1(nrow, &rows)); 10532 nrow = 0; 10533 for (r = 0; r < rEnd - rStart; ++r) 10534 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10535 PetscCall(VecRestoreArrayRead(diag, &a)); 10536 PetscCall(VecDestroy(&diag)); 10537 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10538 } else { 10539 PetscUseTypeMethod(mat, findzerodiagonals, is); 10540 } 10541 PetscFunctionReturn(PETSC_SUCCESS); 10542 } 10543 10544 /*@ 10545 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10546 10547 Collective 10548 10549 Input Parameter: 10550 . mat - the matrix 10551 10552 Output Parameter: 10553 . is - contains the list of rows with off block diagonal entries 10554 10555 Level: developer 10556 10557 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10558 @*/ 10559 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10560 { 10561 PetscFunctionBegin; 10562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10563 PetscValidType(mat, 1); 10564 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10565 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10566 10567 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10568 PetscFunctionReturn(PETSC_SUCCESS); 10569 } 10570 10571 /*@C 10572 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10573 10574 Collective; No Fortran Support 10575 10576 Input Parameter: 10577 . mat - the matrix 10578 10579 Output Parameter: 10580 . values - the block inverses in column major order (FORTRAN-like) 10581 10582 Level: advanced 10583 10584 Notes: 10585 The size of the blocks is determined by the block size of the matrix. 10586 10587 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10588 10589 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10590 10591 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10592 @*/ 10593 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10594 { 10595 PetscFunctionBegin; 10596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10597 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10598 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10599 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10600 PetscFunctionReturn(PETSC_SUCCESS); 10601 } 10602 10603 /*@C 10604 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10605 10606 Collective; No Fortran Support 10607 10608 Input Parameters: 10609 + mat - the matrix 10610 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10611 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10612 10613 Output Parameter: 10614 . values - the block inverses in column major order (FORTRAN-like) 10615 10616 Level: advanced 10617 10618 Notes: 10619 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10620 10621 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10622 10623 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10624 @*/ 10625 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10626 { 10627 PetscFunctionBegin; 10628 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10629 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10630 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10631 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10632 PetscFunctionReturn(PETSC_SUCCESS); 10633 } 10634 10635 /*@ 10636 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10637 10638 Collective 10639 10640 Input Parameters: 10641 + A - the matrix 10642 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10643 10644 Level: advanced 10645 10646 Note: 10647 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10648 10649 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10650 @*/ 10651 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10652 { 10653 const PetscScalar *vals; 10654 PetscInt *dnnz; 10655 PetscInt m, rstart, rend, bs, i, j; 10656 10657 PetscFunctionBegin; 10658 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10659 PetscCall(MatGetBlockSize(A, &bs)); 10660 PetscCall(MatGetLocalSize(A, &m, NULL)); 10661 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10662 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10663 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10664 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10665 PetscCall(PetscFree(dnnz)); 10666 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10667 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10668 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10669 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10670 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10671 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10672 PetscFunctionReturn(PETSC_SUCCESS); 10673 } 10674 10675 /*@C 10676 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10677 via `MatTransposeColoringCreate()`. 10678 10679 Collective 10680 10681 Input Parameter: 10682 . c - coloring context 10683 10684 Level: intermediate 10685 10686 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10687 @*/ 10688 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10689 { 10690 MatTransposeColoring matcolor = *c; 10691 10692 PetscFunctionBegin; 10693 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10694 if (--((PetscObject)matcolor)->refct > 0) { 10695 matcolor = NULL; 10696 PetscFunctionReturn(PETSC_SUCCESS); 10697 } 10698 10699 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10700 PetscCall(PetscFree(matcolor->rows)); 10701 PetscCall(PetscFree(matcolor->den2sp)); 10702 PetscCall(PetscFree(matcolor->colorforcol)); 10703 PetscCall(PetscFree(matcolor->columns)); 10704 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10705 PetscCall(PetscHeaderDestroy(c)); 10706 PetscFunctionReturn(PETSC_SUCCESS); 10707 } 10708 10709 /*@C 10710 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10711 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10712 `MatTransposeColoring` to sparse `B`. 10713 10714 Collective 10715 10716 Input Parameters: 10717 + coloring - coloring context created with `MatTransposeColoringCreate()` 10718 - B - sparse matrix 10719 10720 Output Parameter: 10721 . Btdense - dense matrix $B^T$ 10722 10723 Level: developer 10724 10725 Note: 10726 These are used internally for some implementations of `MatRARt()` 10727 10728 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10729 @*/ 10730 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10731 { 10732 PetscFunctionBegin; 10733 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10734 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10735 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10736 10737 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10738 PetscFunctionReturn(PETSC_SUCCESS); 10739 } 10740 10741 /*@C 10742 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10743 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10744 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10745 $C_{sp}$ from $C_{den}$. 10746 10747 Collective 10748 10749 Input Parameters: 10750 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10751 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10752 10753 Output Parameter: 10754 . Csp - sparse matrix 10755 10756 Level: developer 10757 10758 Note: 10759 These are used internally for some implementations of `MatRARt()` 10760 10761 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10762 @*/ 10763 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10764 { 10765 PetscFunctionBegin; 10766 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10767 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10768 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10769 10770 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10771 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10772 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10773 PetscFunctionReturn(PETSC_SUCCESS); 10774 } 10775 10776 /*@C 10777 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10778 10779 Collective 10780 10781 Input Parameters: 10782 + mat - the matrix product C 10783 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10784 10785 Output Parameter: 10786 . color - the new coloring context 10787 10788 Level: intermediate 10789 10790 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10791 `MatTransColoringApplyDenToSp()` 10792 @*/ 10793 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10794 { 10795 MatTransposeColoring c; 10796 MPI_Comm comm; 10797 10798 PetscFunctionBegin; 10799 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10800 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10801 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10802 10803 c->ctype = iscoloring->ctype; 10804 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10805 10806 *color = c; 10807 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10808 PetscFunctionReturn(PETSC_SUCCESS); 10809 } 10810 10811 /*@ 10812 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10813 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10814 same, otherwise it will be larger 10815 10816 Not Collective 10817 10818 Input Parameter: 10819 . mat - the matrix 10820 10821 Output Parameter: 10822 . state - the current state 10823 10824 Level: intermediate 10825 10826 Notes: 10827 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10828 different matrices 10829 10830 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10831 10832 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10833 10834 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10835 @*/ 10836 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10837 { 10838 PetscFunctionBegin; 10839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10840 *state = mat->nonzerostate; 10841 PetscFunctionReturn(PETSC_SUCCESS); 10842 } 10843 10844 /*@ 10845 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10846 matrices from each processor 10847 10848 Collective 10849 10850 Input Parameters: 10851 + comm - the communicators the parallel matrix will live on 10852 . seqmat - the input sequential matrices 10853 . n - number of local columns (or `PETSC_DECIDE`) 10854 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10855 10856 Output Parameter: 10857 . mpimat - the parallel matrix generated 10858 10859 Level: developer 10860 10861 Note: 10862 The number of columns of the matrix in EACH processor MUST be the same. 10863 10864 .seealso: [](ch_matrices), `Mat` 10865 @*/ 10866 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10867 { 10868 PetscMPIInt size; 10869 10870 PetscFunctionBegin; 10871 PetscCallMPI(MPI_Comm_size(comm, &size)); 10872 if (size == 1) { 10873 if (reuse == MAT_INITIAL_MATRIX) { 10874 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10875 } else { 10876 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10877 } 10878 PetscFunctionReturn(PETSC_SUCCESS); 10879 } 10880 10881 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"); 10882 10883 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10884 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10885 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10886 PetscFunctionReturn(PETSC_SUCCESS); 10887 } 10888 10889 /*@ 10890 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10891 10892 Collective 10893 10894 Input Parameters: 10895 + A - the matrix to create subdomains from 10896 - N - requested number of subdomains 10897 10898 Output Parameters: 10899 + n - number of subdomains resulting on this MPI process 10900 - iss - `IS` list with indices of subdomains on this MPI process 10901 10902 Level: advanced 10903 10904 Note: 10905 The number of subdomains must be smaller than the communicator size 10906 10907 .seealso: [](ch_matrices), `Mat`, `IS` 10908 @*/ 10909 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10910 { 10911 MPI_Comm comm, subcomm; 10912 PetscMPIInt size, rank, color; 10913 PetscInt rstart, rend, k; 10914 10915 PetscFunctionBegin; 10916 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10917 PetscCallMPI(MPI_Comm_size(comm, &size)); 10918 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10919 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); 10920 *n = 1; 10921 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10922 color = rank / k; 10923 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10924 PetscCall(PetscMalloc1(1, iss)); 10925 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10926 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10927 PetscCallMPI(MPI_Comm_free(&subcomm)); 10928 PetscFunctionReturn(PETSC_SUCCESS); 10929 } 10930 10931 /*@ 10932 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10933 10934 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10935 If they are not the same, uses `MatMatMatMult()`. 10936 10937 Once the coarse grid problem is constructed, correct for interpolation operators 10938 that are not of full rank, which can legitimately happen in the case of non-nested 10939 geometric multigrid. 10940 10941 Input Parameters: 10942 + restrct - restriction operator 10943 . dA - fine grid matrix 10944 . interpolate - interpolation operator 10945 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10946 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10947 10948 Output Parameter: 10949 . A - the Galerkin coarse matrix 10950 10951 Options Database Key: 10952 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10953 10954 Level: developer 10955 10956 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10957 @*/ 10958 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10959 { 10960 IS zerorows; 10961 Vec diag; 10962 10963 PetscFunctionBegin; 10964 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10965 /* Construct the coarse grid matrix */ 10966 if (interpolate == restrct) { 10967 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10968 } else { 10969 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10970 } 10971 10972 /* If the interpolation matrix is not of full rank, A will have zero rows. 10973 This can legitimately happen in the case of non-nested geometric multigrid. 10974 In that event, we set the rows of the matrix to the rows of the identity, 10975 ignoring the equations (as the RHS will also be zero). */ 10976 10977 PetscCall(MatFindZeroRows(*A, &zerorows)); 10978 10979 if (zerorows != NULL) { /* if there are any zero rows */ 10980 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10981 PetscCall(MatGetDiagonal(*A, diag)); 10982 PetscCall(VecISSet(diag, zerorows, 1.0)); 10983 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10984 PetscCall(VecDestroy(&diag)); 10985 PetscCall(ISDestroy(&zerorows)); 10986 } 10987 PetscFunctionReturn(PETSC_SUCCESS); 10988 } 10989 10990 /*@C 10991 MatSetOperation - Allows user to set a matrix operation for any matrix type 10992 10993 Logically Collective 10994 10995 Input Parameters: 10996 + mat - the matrix 10997 . op - the name of the operation 10998 - f - the function that provides the operation 10999 11000 Level: developer 11001 11002 Example Usage: 11003 .vb 11004 extern PetscErrorCode usermult(Mat, Vec, Vec); 11005 11006 PetscCall(MatCreateXXX(comm, ..., &A)); 11007 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 11008 .ve 11009 11010 Notes: 11011 See the file `include/petscmat.h` for a complete list of matrix 11012 operations, which all have the form MATOP_<OPERATION>, where 11013 <OPERATION> is the name (in all capital letters) of the 11014 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11015 11016 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11017 sequence as the usual matrix interface routines, since they 11018 are intended to be accessed via the usual matrix interface 11019 routines, e.g., 11020 .vb 11021 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11022 .ve 11023 11024 In particular each function MUST return `PETSC_SUCCESS` on success and 11025 nonzero on failure. 11026 11027 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11028 11029 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11030 @*/ 11031 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11032 { 11033 PetscFunctionBegin; 11034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11035 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11036 (((void (**)(void))mat->ops)[op]) = f; 11037 PetscFunctionReturn(PETSC_SUCCESS); 11038 } 11039 11040 /*@C 11041 MatGetOperation - Gets a matrix operation for any matrix type. 11042 11043 Not Collective 11044 11045 Input Parameters: 11046 + mat - the matrix 11047 - op - the name of the operation 11048 11049 Output Parameter: 11050 . f - the function that provides the operation 11051 11052 Level: developer 11053 11054 Example Usage: 11055 .vb 11056 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11057 11058 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11059 .ve 11060 11061 Notes: 11062 See the file include/petscmat.h for a complete list of matrix 11063 operations, which all have the form MATOP_<OPERATION>, where 11064 <OPERATION> is the name (in all capital letters) of the 11065 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11066 11067 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11068 11069 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11070 @*/ 11071 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11072 { 11073 PetscFunctionBegin; 11074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11075 *f = (((void (**)(void))mat->ops)[op]); 11076 PetscFunctionReturn(PETSC_SUCCESS); 11077 } 11078 11079 /*@ 11080 MatHasOperation - Determines whether the given matrix supports the particular operation. 11081 11082 Not Collective 11083 11084 Input Parameters: 11085 + mat - the matrix 11086 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11087 11088 Output Parameter: 11089 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11090 11091 Level: advanced 11092 11093 Note: 11094 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11095 11096 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11097 @*/ 11098 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11099 { 11100 PetscFunctionBegin; 11101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11102 PetscAssertPointer(has, 3); 11103 if (mat->ops->hasoperation) { 11104 PetscUseTypeMethod(mat, hasoperation, op, has); 11105 } else { 11106 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11107 else { 11108 *has = PETSC_FALSE; 11109 if (op == MATOP_CREATE_SUBMATRIX) { 11110 PetscMPIInt size; 11111 11112 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11113 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11114 } 11115 } 11116 } 11117 PetscFunctionReturn(PETSC_SUCCESS); 11118 } 11119 11120 /*@ 11121 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11122 11123 Collective 11124 11125 Input Parameter: 11126 . mat - the matrix 11127 11128 Output Parameter: 11129 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11130 11131 Level: beginner 11132 11133 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11134 @*/ 11135 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11136 { 11137 PetscFunctionBegin; 11138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11139 PetscValidType(mat, 1); 11140 PetscAssertPointer(cong, 2); 11141 if (!mat->rmap || !mat->cmap) { 11142 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11143 PetscFunctionReturn(PETSC_SUCCESS); 11144 } 11145 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11146 PetscCall(PetscLayoutSetUp(mat->rmap)); 11147 PetscCall(PetscLayoutSetUp(mat->cmap)); 11148 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11149 if (*cong) mat->congruentlayouts = 1; 11150 else mat->congruentlayouts = 0; 11151 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11152 PetscFunctionReturn(PETSC_SUCCESS); 11153 } 11154 11155 PetscErrorCode MatSetInf(Mat A) 11156 { 11157 PetscFunctionBegin; 11158 PetscUseTypeMethod(A, setinf); 11159 PetscFunctionReturn(PETSC_SUCCESS); 11160 } 11161 11162 /*@C 11163 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 11164 and possibly removes small values from the graph structure. 11165 11166 Collective 11167 11168 Input Parameters: 11169 + A - the matrix 11170 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11171 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11172 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11173 . num_idx - size of 'index' array 11174 - index - array of block indices to use for graph strength of connection weight 11175 11176 Output Parameter: 11177 . graph - the resulting graph 11178 11179 Level: advanced 11180 11181 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11182 @*/ 11183 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11184 { 11185 PetscFunctionBegin; 11186 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11187 PetscValidType(A, 1); 11188 PetscValidLogicalCollectiveBool(A, scale, 3); 11189 PetscAssertPointer(graph, 7); 11190 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11191 PetscFunctionReturn(PETSC_SUCCESS); 11192 } 11193 11194 /*@ 11195 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11196 meaning the same memory is used for the matrix, and no new memory is allocated. 11197 11198 Collective 11199 11200 Input Parameters: 11201 + A - the matrix 11202 - 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 11203 11204 Level: intermediate 11205 11206 Developer Note: 11207 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11208 of the arrays in the data structure are unneeded. 11209 11210 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11211 @*/ 11212 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11213 { 11214 PetscFunctionBegin; 11215 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11216 PetscUseTypeMethod(A, eliminatezeros, keep); 11217 PetscFunctionReturn(PETSC_SUCCESS); 11218 } 11219