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, MAT_HIPCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 71 72 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 73 74 It generates an error if used on unassembled sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n, st; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 207 PetscCall(MatGetSize(mat, &N, NULL)); 208 PetscCall(MatGetLocalSize(mat, &n, NULL)); 209 PetscCall(VecSet(l, 0.0)); 210 PetscCall(VecSetRandom(r, NULL)); 211 PetscCall(MatMult(mat, r, l)); 212 PetscCall(VecGetArrayRead(l, &al)); 213 } else { /* nonzero columns */ 214 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 215 PetscCall(MatGetSize(mat, NULL, &N)); 216 PetscCall(MatGetLocalSize(mat, NULL, &n)); 217 PetscCall(VecSet(r, 0.0)); 218 PetscCall(VecSetRandom(l, NULL)); 219 PetscCall(MatMultTranspose(mat, l, r)); 220 PetscCall(VecGetArrayRead(r, &al)); 221 } 222 if (tol <= 0.0) { 223 for (i = 0, nz = 0; i < n; i++) 224 if (al[i] != 0.0) nz++; 225 } else { 226 for (i = 0, nz = 0; i < n; i++) 227 if (PetscAbsScalar(al[i]) > tol) nz++; 228 } 229 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 230 if (gnz != N) { 231 PetscInt *nzr; 232 PetscCall(PetscMalloc1(nz, &nzr)); 233 if (nz) { 234 if (tol < 0) { 235 for (i = 0, nz = 0; i < n; i++) 236 if (al[i] != 0.0) nzr[nz++] = i + st; 237 } else { 238 for (i = 0, nz = 0; i < n; i++) 239 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 240 } 241 } 242 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 243 } else *nonzero = NULL; 244 if (!cols) { /* nonzero rows */ 245 PetscCall(VecRestoreArrayRead(l, &al)); 246 } else { 247 PetscCall(VecRestoreArrayRead(r, &al)); 248 } 249 PetscCall(VecDestroy(&l)); 250 PetscCall(VecDestroy(&r)); 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 /*@ 255 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 256 257 Input Parameter: 258 . mat - the matrix 259 260 Output Parameter: 261 . keptrows - the rows that are not completely zero 262 263 Level: intermediate 264 265 Note: 266 `keptrows` is set to `NULL` if all rows are nonzero. 267 268 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 269 @*/ 270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 271 { 272 PetscFunctionBegin; 273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 274 PetscValidType(mat, 1); 275 PetscAssertPointer(keptrows, 2); 276 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 277 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 278 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 279 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 280 PetscFunctionReturn(PETSC_SUCCESS); 281 } 282 283 /*@ 284 MatFindZeroRows - Locate all rows that are completely zero in the matrix 285 286 Input Parameter: 287 . mat - the matrix 288 289 Output Parameter: 290 . zerorows - the rows that are completely zero 291 292 Level: intermediate 293 294 Note: 295 `zerorows` is set to `NULL` if no rows are zero. 296 297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 298 @*/ 299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 300 { 301 IS keptrows; 302 PetscInt m, n; 303 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 306 PetscValidType(mat, 1); 307 PetscAssertPointer(zerorows, 2); 308 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 309 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 310 In keeping with this convention, we set zerorows to NULL if there are no zero 311 rows. */ 312 if (keptrows == NULL) { 313 *zerorows = NULL; 314 } else { 315 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 316 PetscCall(ISComplement(keptrows, m, n, zerorows)); 317 PetscCall(ISDestroy(&keptrows)); 318 } 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 324 325 Not Collective 326 327 Input Parameter: 328 . A - the matrix 329 330 Output Parameter: 331 . a - the diagonal part (which is a SEQUENTIAL matrix) 332 333 Level: advanced 334 335 Notes: 336 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 337 338 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 339 340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 341 @*/ 342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 343 { 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 346 PetscValidType(A, 1); 347 PetscAssertPointer(a, 2); 348 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 349 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 350 else { 351 PetscMPIInt size; 352 353 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 354 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 355 *a = A; 356 } 357 PetscFunctionReturn(PETSC_SUCCESS); 358 } 359 360 /*@ 361 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 362 363 Collective 364 365 Input Parameter: 366 . mat - the matrix 367 368 Output Parameter: 369 . trace - the sum of the diagonal entries 370 371 Level: advanced 372 373 .seealso: [](ch_matrices), `Mat` 374 @*/ 375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 376 { 377 Vec diag; 378 379 PetscFunctionBegin; 380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 381 PetscAssertPointer(trace, 2); 382 PetscCall(MatCreateVecs(mat, &diag, NULL)); 383 PetscCall(MatGetDiagonal(mat, diag)); 384 PetscCall(VecSum(diag, trace)); 385 PetscCall(VecDestroy(&diag)); 386 PetscFunctionReturn(PETSC_SUCCESS); 387 } 388 389 /*@ 390 MatRealPart - Zeros out the imaginary part of the matrix 391 392 Logically Collective 393 394 Input Parameter: 395 . mat - the matrix 396 397 Level: advanced 398 399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 400 @*/ 401 PetscErrorCode MatRealPart(Mat mat) 402 { 403 PetscFunctionBegin; 404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 405 PetscValidType(mat, 1); 406 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 407 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 408 MatCheckPreallocated(mat, 1); 409 PetscUseTypeMethod(mat, realpart); 410 PetscFunctionReturn(PETSC_SUCCESS); 411 } 412 413 /*@C 414 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 415 416 Collective 417 418 Input Parameter: 419 . mat - the matrix 420 421 Output Parameters: 422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 423 - ghosts - the global indices of the ghost points 424 425 Level: advanced 426 427 Note: 428 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 429 430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 431 @*/ 432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 433 { 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 436 PetscValidType(mat, 1); 437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 439 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 440 else { 441 if (nghosts) *nghosts = 0; 442 if (ghosts) *ghosts = NULL; 443 } 444 PetscFunctionReturn(PETSC_SUCCESS); 445 } 446 447 /*@ 448 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 449 450 Logically Collective 451 452 Input Parameter: 453 . mat - the matrix 454 455 Level: advanced 456 457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 458 @*/ 459 PetscErrorCode MatImaginaryPart(Mat mat) 460 { 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 463 PetscValidType(mat, 1); 464 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 465 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 466 MatCheckPreallocated(mat, 1); 467 PetscUseTypeMethod(mat, imaginarypart); 468 PetscFunctionReturn(PETSC_SUCCESS); 469 } 470 471 /*@ 472 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 473 474 Not Collective 475 476 Input Parameter: 477 . mat - the matrix 478 479 Output Parameters: 480 + missing - is any diagonal entry missing 481 - dd - first diagonal entry that is missing (optional) on this process 482 483 Level: advanced 484 485 Note: 486 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 487 488 .seealso: [](ch_matrices), `Mat` 489 @*/ 490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 491 { 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 494 PetscValidType(mat, 1); 495 PetscAssertPointer(missing, 2); 496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 498 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 503 /*@C 504 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 505 for each row that you get to ensure that your application does 506 not bleed memory. 507 508 Not Collective 509 510 Input Parameters: 511 + mat - the matrix 512 - row - the row to get 513 514 Output Parameters: 515 + ncols - if not `NULL`, the number of nonzeros in `row` 516 . cols - if not `NULL`, the column numbers 517 - vals - if not `NULL`, the numerical values 518 519 Level: advanced 520 521 Notes: 522 This routine is provided for people who need to have direct access 523 to the structure of a matrix. We hope that we provide enough 524 high-level matrix routines that few users will need it. 525 526 `MatGetRow()` always returns 0-based column indices, regardless of 527 whether the internal representation is 0-based (default) or 1-based. 528 529 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 530 not wish to extract these quantities. 531 532 The user can only examine the values extracted with `MatGetRow()`; 533 the values CANNOT be altered. To change the matrix entries, one 534 must use `MatSetValues()`. 535 536 You can only have one call to `MatGetRow()` outstanding for a particular 537 matrix at a time, per processor. `MatGetRow()` can only obtain rows 538 associated with the given processor, it cannot get rows from the 539 other processors; for that we suggest using `MatCreateSubMatrices()`, then 540 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 541 is in the global number of rows. 542 543 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 544 545 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 546 547 Fortran Note: 548 The calling sequence is 549 .vb 550 MatGetRow(matrix,row,ncols,cols,values,ierr) 551 Mat matrix (input) 552 integer row (input) 553 integer ncols (output) 554 integer cols(maxcols) (output) 555 double precision (or double complex) values(maxcols) output 556 .ve 557 where maxcols >= maximum nonzeros in any row of the matrix. 558 559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 560 @*/ 561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 562 { 563 PetscInt incols; 564 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 567 PetscValidType(mat, 1); 568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 570 MatCheckPreallocated(mat, 1); 571 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 572 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 573 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 574 if (ncols) *ncols = incols; 575 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 576 PetscFunctionReturn(PETSC_SUCCESS); 577 } 578 579 /*@ 580 MatConjugate - replaces the matrix values with their complex conjugates 581 582 Logically Collective 583 584 Input Parameter: 585 . mat - the matrix 586 587 Level: advanced 588 589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 590 @*/ 591 PetscErrorCode MatConjugate(Mat mat) 592 { 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 596 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 597 PetscUseTypeMethod(mat, conjugate); 598 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 599 } 600 PetscFunctionReturn(PETSC_SUCCESS); 601 } 602 603 /*@C 604 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 605 606 Not Collective 607 608 Input Parameters: 609 + mat - the matrix 610 . row - the row to get 611 . ncols - the number of nonzeros 612 . cols - the columns of the nonzeros 613 - vals - if nonzero the column values 614 615 Level: advanced 616 617 Notes: 618 This routine should be called after you have finished examining the entries. 619 620 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 621 us of the array after it has been restored. If you pass `NULL`, it will 622 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 623 624 Fortran Notes: 625 The calling sequence is 626 .vb 627 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 628 Mat matrix (input) 629 integer row (input) 630 integer ncols (output) 631 integer cols(maxcols) (output) 632 double precision (or double complex) values(maxcols) output 633 .ve 634 Where maxcols >= maximum nonzeros in any row of the matrix. 635 636 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 637 before another call to `MatGetRow()` can be made. 638 639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 640 @*/ 641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 642 { 643 PetscFunctionBegin; 644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 645 if (ncols) PetscAssertPointer(ncols, 3); 646 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 647 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 648 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 649 if (ncols) *ncols = 0; 650 if (cols) *cols = NULL; 651 if (vals) *vals = NULL; 652 PetscFunctionReturn(PETSC_SUCCESS); 653 } 654 655 /*@ 656 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 657 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 658 659 Not Collective 660 661 Input Parameter: 662 . mat - the matrix 663 664 Level: advanced 665 666 Note: 667 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 668 669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 670 @*/ 671 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 672 { 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 675 PetscValidType(mat, 1); 676 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 677 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 678 MatCheckPreallocated(mat, 1); 679 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 680 PetscUseTypeMethod(mat, getrowuppertriangular); 681 PetscFunctionReturn(PETSC_SUCCESS); 682 } 683 684 /*@ 685 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 686 687 Not Collective 688 689 Input Parameter: 690 . mat - the matrix 691 692 Level: advanced 693 694 Note: 695 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 696 697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 698 @*/ 699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 700 { 701 PetscFunctionBegin; 702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 703 PetscValidType(mat, 1); 704 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 705 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 706 MatCheckPreallocated(mat, 1); 707 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 708 PetscUseTypeMethod(mat, restorerowuppertriangular); 709 PetscFunctionReturn(PETSC_SUCCESS); 710 } 711 712 /*@ 713 MatSetOptionsPrefix - Sets the prefix used for searching for all 714 `Mat` options in the database. 715 716 Logically Collective 717 718 Input Parameters: 719 + A - the matrix 720 - prefix - the prefix to prepend to all option names 721 722 Level: advanced 723 724 Notes: 725 A hyphen (-) must NOT be given at the beginning of the prefix name. 726 The first character of all runtime options is AUTOMATICALLY the hyphen. 727 728 This is NOT used for options for the factorization of the matrix. Normally the 729 prefix is automatically passed in from the PC calling the factorization. To set 730 it directly use `MatSetOptionsPrefixFactor()` 731 732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 733 @*/ 734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 735 { 736 PetscFunctionBegin; 737 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 738 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 739 PetscFunctionReturn(PETSC_SUCCESS); 740 } 741 742 /*@ 743 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 744 for matrices created with `MatGetFactor()` 745 746 Logically Collective 747 748 Input Parameters: 749 + A - the matrix 750 - prefix - the prefix to prepend to all option names for the factored matrix 751 752 Level: developer 753 754 Notes: 755 A hyphen (-) must NOT be given at the beginning of the prefix name. 756 The first character of all runtime options is AUTOMATICALLY the hyphen. 757 758 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 759 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 760 761 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 762 @*/ 763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 764 { 765 PetscFunctionBegin; 766 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 767 if (prefix) { 768 PetscAssertPointer(prefix, 2); 769 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 770 if (prefix != A->factorprefix) { 771 PetscCall(PetscFree(A->factorprefix)); 772 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 773 } 774 } else PetscCall(PetscFree(A->factorprefix)); 775 PetscFunctionReturn(PETSC_SUCCESS); 776 } 777 778 /*@ 779 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 780 for matrices created with `MatGetFactor()` 781 782 Logically Collective 783 784 Input Parameters: 785 + A - the matrix 786 - prefix - the prefix to prepend to all option names for the factored matrix 787 788 Level: developer 789 790 Notes: 791 A hyphen (-) must NOT be given at the beginning of the prefix name. 792 The first character of all runtime options is AUTOMATICALLY the hyphen. 793 794 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 795 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 796 797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 798 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 799 `MatSetOptionsPrefix()` 800 @*/ 801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 802 { 803 size_t len1, len2, new_len; 804 805 PetscFunctionBegin; 806 PetscValidHeader(A, 1); 807 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 808 if (!A->factorprefix) { 809 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 810 PetscFunctionReturn(PETSC_SUCCESS); 811 } 812 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 813 814 PetscCall(PetscStrlen(A->factorprefix, &len1)); 815 PetscCall(PetscStrlen(prefix, &len2)); 816 new_len = len1 + len2 + 1; 817 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 818 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 819 PetscFunctionReturn(PETSC_SUCCESS); 820 } 821 822 /*@ 823 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 824 matrix options in the database. 825 826 Logically Collective 827 828 Input Parameters: 829 + A - the matrix 830 - prefix - the prefix to prepend to all option names 831 832 Level: advanced 833 834 Note: 835 A hyphen (-) must NOT be given at the beginning of the prefix name. 836 The first character of all runtime options is AUTOMATICALLY the hyphen. 837 838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 839 @*/ 840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 844 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 845 PetscFunctionReturn(PETSC_SUCCESS); 846 } 847 848 /*@ 849 MatGetOptionsPrefix - Gets the prefix used for searching for all 850 matrix options in the database. 851 852 Not Collective 853 854 Input Parameter: 855 . A - the matrix 856 857 Output Parameter: 858 . prefix - pointer to the prefix string used 859 860 Level: advanced 861 862 Fortran Note: 863 The user should pass in a string `prefix` of 864 sufficient length to hold the prefix. 865 866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 867 @*/ 868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 869 { 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 872 PetscAssertPointer(prefix, 2); 873 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 874 PetscFunctionReturn(PETSC_SUCCESS); 875 } 876 877 /*@C 878 MatGetState - Gets the state of a `Mat`. 879 880 Not Collective 881 882 Input Parameter: 883 . A - the matrix 884 885 Output Parameter: 886 . state - the object state 887 888 Level: advanced 889 890 Note: 891 Object state is an integer which gets increased every time 892 the object is changed. By saving and later querying the object state 893 one can determine whether information about the object is still current. 894 895 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()` 896 @*/ 897 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 898 { 899 PetscFunctionBegin; 900 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 901 PetscAssertPointer(state, 2); 902 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 903 PetscFunctionReturn(PETSC_SUCCESS); 904 } 905 906 /*@ 907 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 908 909 Collective 910 911 Input Parameter: 912 . A - the matrix 913 914 Level: beginner 915 916 Notes: 917 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 918 919 Users can reset the preallocation to access the original memory. 920 921 Currently only supported for `MATAIJ` matrices. 922 923 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 924 @*/ 925 PetscErrorCode MatResetPreallocation(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 PetscValidType(A, 1); 930 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 931 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 932 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 933 PetscFunctionReturn(PETSC_SUCCESS); 934 } 935 936 /*@ 937 MatSetUp - Sets up the internal matrix data structures for later use. 938 939 Collective 940 941 Input Parameter: 942 . A - the matrix 943 944 Level: intermediate 945 946 Notes: 947 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 948 setting values in the matrix. 949 950 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 951 952 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 953 @*/ 954 PetscErrorCode MatSetUp(Mat A) 955 { 956 PetscFunctionBegin; 957 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 958 if (!((PetscObject)A)->type_name) { 959 PetscMPIInt size; 960 961 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 962 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 963 } 964 if (!A->preallocated) PetscTryTypeMethod(A, setup); 965 PetscCall(PetscLayoutSetUp(A->rmap)); 966 PetscCall(PetscLayoutSetUp(A->cmap)); 967 A->preallocated = PETSC_TRUE; 968 PetscFunctionReturn(PETSC_SUCCESS); 969 } 970 971 #if defined(PETSC_HAVE_SAWS) 972 #include <petscviewersaws.h> 973 #endif 974 975 /* 976 If threadsafety is on extraneous matrices may be printed 977 978 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 979 */ 980 #if !defined(PETSC_HAVE_THREADSAFETY) 981 static PetscInt insidematview = 0; 982 #endif 983 984 /*@C 985 MatViewFromOptions - View properties of the matrix based on options set in the options database 986 987 Collective 988 989 Input Parameters: 990 + A - the matrix 991 . obj - optional additional object that provides the options prefix to use 992 - name - command line option 993 994 Options Database Key: 995 . -mat_view [viewertype]:... - the viewer and its options 996 997 Level: intermediate 998 999 Note: 1000 .vb 1001 If no value is provided ascii:stdout is used 1002 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1003 for example ascii::ascii_info prints just the information about the object not all details 1004 unless :append is given filename opens in write mode, overwriting what was already there 1005 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1006 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1007 socket[:port] defaults to the standard output port 1008 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1009 .ve 1010 1011 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1012 @*/ 1013 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1014 { 1015 PetscFunctionBegin; 1016 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1017 #if !defined(PETSC_HAVE_THREADSAFETY) 1018 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1019 #endif 1020 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1021 PetscFunctionReturn(PETSC_SUCCESS); 1022 } 1023 1024 /*@C 1025 MatView - display information about a matrix in a variety ways 1026 1027 Collective on viewer 1028 1029 Input Parameters: 1030 + mat - the matrix 1031 - viewer - visualization context 1032 1033 Options Database Keys: 1034 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1035 . -mat_view ::ascii_info_detail - Prints more detailed info 1036 . -mat_view - Prints matrix in ASCII format 1037 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1038 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1039 . -display <name> - Sets display name (default is host) 1040 . -draw_pause <sec> - Sets number of seconds to pause after display 1041 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1042 . -viewer_socket_machine <machine> - - 1043 . -viewer_socket_port <port> - - 1044 . -mat_view binary - save matrix to file in binary format 1045 - -viewer_binary_filename <name> - - 1046 1047 Level: beginner 1048 1049 Notes: 1050 The available visualization contexts include 1051 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1052 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1053 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1054 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1055 1056 The user can open alternative visualization contexts with 1057 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1058 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1059 specified file; corresponding input uses `MatLoad()` 1060 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1061 an X window display 1062 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1063 Currently only the `MATSEQDENSE` and `MATAIJ` 1064 matrix types support the Socket viewer. 1065 1066 The user can call `PetscViewerPushFormat()` to specify the output 1067 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1068 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1069 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1070 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1071 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1072 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1073 format common among all matrix types 1074 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1075 format (which is in many cases the same as the default) 1076 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1077 size and structure (not the matrix entries) 1078 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1079 the matrix structure 1080 1081 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1082 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1083 1084 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1085 1086 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1087 viewer is used. 1088 1089 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1090 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1091 1092 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1093 and then use the following mouse functions. 1094 .vb 1095 left mouse: zoom in 1096 middle mouse: zoom out 1097 right mouse: continue with the simulation 1098 .ve 1099 1100 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1101 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1102 @*/ 1103 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1104 { 1105 PetscInt rows, cols, rbs, cbs; 1106 PetscBool isascii, isstring, issaws; 1107 PetscViewerFormat format; 1108 PetscMPIInt size; 1109 1110 PetscFunctionBegin; 1111 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1112 PetscValidType(mat, 1); 1113 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1114 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1115 1116 PetscCall(PetscViewerGetFormat(viewer, &format)); 1117 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1118 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1119 1120 #if !defined(PETSC_HAVE_THREADSAFETY) 1121 insidematview++; 1122 #endif 1123 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1124 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1125 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1126 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1127 1128 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1129 if (isascii) { 1130 if (!mat->preallocated) { 1131 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1132 #if !defined(PETSC_HAVE_THREADSAFETY) 1133 insidematview--; 1134 #endif 1135 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1136 PetscFunctionReturn(PETSC_SUCCESS); 1137 } 1138 if (!mat->assembled) { 1139 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1140 #if !defined(PETSC_HAVE_THREADSAFETY) 1141 insidematview--; 1142 #endif 1143 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1144 PetscFunctionReturn(PETSC_SUCCESS); 1145 } 1146 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1147 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1148 MatNullSpace nullsp, transnullsp; 1149 1150 PetscCall(PetscViewerASCIIPushTab(viewer)); 1151 PetscCall(MatGetSize(mat, &rows, &cols)); 1152 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1153 if (rbs != 1 || cbs != 1) { 1154 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : "")); 1155 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1156 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1157 if (mat->factortype) { 1158 MatSolverType solver; 1159 PetscCall(MatFactorGetSolverType(mat, &solver)); 1160 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1161 } 1162 if (mat->ops->getinfo) { 1163 MatInfo info; 1164 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1165 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1166 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1167 } 1168 PetscCall(MatGetNullSpace(mat, &nullsp)); 1169 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1170 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1171 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1172 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1173 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1174 PetscCall(PetscViewerASCIIPushTab(viewer)); 1175 PetscCall(MatProductView(mat, viewer)); 1176 PetscCall(PetscViewerASCIIPopTab(viewer)); 1177 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1178 IS tmp; 1179 1180 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1181 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1182 PetscCall(PetscViewerASCIIPushTab(viewer)); 1183 PetscCall(ISView(tmp, viewer)); 1184 PetscCall(PetscViewerASCIIPopTab(viewer)); 1185 PetscCall(ISDestroy(&tmp)); 1186 } 1187 } 1188 } else if (issaws) { 1189 #if defined(PETSC_HAVE_SAWS) 1190 PetscMPIInt rank; 1191 1192 PetscCall(PetscObjectName((PetscObject)mat)); 1193 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1194 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1195 #endif 1196 } else if (isstring) { 1197 const char *type; 1198 PetscCall(MatGetType(mat, &type)); 1199 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1200 PetscTryTypeMethod(mat, view, viewer); 1201 } 1202 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1203 PetscCall(PetscViewerASCIIPushTab(viewer)); 1204 PetscUseTypeMethod(mat, viewnative, viewer); 1205 PetscCall(PetscViewerASCIIPopTab(viewer)); 1206 } else if (mat->ops->view) { 1207 PetscCall(PetscViewerASCIIPushTab(viewer)); 1208 PetscUseTypeMethod(mat, view, viewer); 1209 PetscCall(PetscViewerASCIIPopTab(viewer)); 1210 } 1211 if (isascii) { 1212 PetscCall(PetscViewerGetFormat(viewer, &format)); 1213 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1214 } 1215 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1216 #if !defined(PETSC_HAVE_THREADSAFETY) 1217 insidematview--; 1218 #endif 1219 PetscFunctionReturn(PETSC_SUCCESS); 1220 } 1221 1222 #if defined(PETSC_USE_DEBUG) 1223 #include <../src/sys/totalview/tv_data_display.h> 1224 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1225 { 1226 TV_add_row("Local rows", "int", &mat->rmap->n); 1227 TV_add_row("Local columns", "int", &mat->cmap->n); 1228 TV_add_row("Global rows", "int", &mat->rmap->N); 1229 TV_add_row("Global columns", "int", &mat->cmap->N); 1230 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1231 return TV_format_OK; 1232 } 1233 #endif 1234 1235 /*@C 1236 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1237 with `MatView()`. The matrix format is determined from the options database. 1238 Generates a parallel MPI matrix if the communicator has more than one 1239 processor. The default matrix type is `MATAIJ`. 1240 1241 Collective 1242 1243 Input Parameters: 1244 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1245 or some related function before a call to `MatLoad()` 1246 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1247 1248 Options Database Key: 1249 . -matload_block_size <bs> - set block size 1250 1251 Level: beginner 1252 1253 Notes: 1254 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1255 `Mat` before calling this routine if you wish to set it from the options database. 1256 1257 `MatLoad()` automatically loads into the options database any options 1258 given in the file filename.info where filename is the name of the file 1259 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1260 file will be ignored if you use the -viewer_binary_skip_info option. 1261 1262 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1263 sets the default matrix type AIJ and sets the local and global sizes. 1264 If type and/or size is already set, then the same are used. 1265 1266 In parallel, each processor can load a subset of rows (or the 1267 entire matrix). This routine is especially useful when a large 1268 matrix is stored on disk and only part of it is desired on each 1269 processor. For example, a parallel solver may access only some of 1270 the rows from each processor. The algorithm used here reads 1271 relatively small blocks of data rather than reading the entire 1272 matrix and then subsetting it. 1273 1274 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1275 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1276 or the sequence like 1277 .vb 1278 `PetscViewer` v; 1279 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1280 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1281 `PetscViewerSetFromOptions`(v); 1282 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1283 `PetscViewerFileSetName`(v,"datafile"); 1284 .ve 1285 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1286 $ -viewer_type {binary, hdf5} 1287 1288 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1289 and src/mat/tutorials/ex10.c with the second approach. 1290 1291 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1292 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1293 Multiple objects, both matrices and vectors, can be stored within the same file. 1294 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1295 1296 Most users should not need to know the details of the binary storage 1297 format, since `MatLoad()` and `MatView()` completely hide these details. 1298 But for anyone who is interested, the standard binary matrix storage 1299 format is 1300 1301 .vb 1302 PetscInt MAT_FILE_CLASSID 1303 PetscInt number of rows 1304 PetscInt number of columns 1305 PetscInt total number of nonzeros 1306 PetscInt *number nonzeros in each row 1307 PetscInt *column indices of all nonzeros (starting index is zero) 1308 PetscScalar *values of all nonzeros 1309 .ve 1310 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1311 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 1312 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1313 1314 PETSc automatically does the byte swapping for 1315 machines that store the bytes reversed. Thus if you write your own binary 1316 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1317 and `PetscBinaryWrite()` to see how this may be done. 1318 1319 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1320 Each processor's chunk is loaded independently by its owning MPI process. 1321 Multiple objects, both matrices and vectors, can be stored within the same file. 1322 They are looked up by their PetscObject name. 1323 1324 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1325 by default the same structure and naming of the AIJ arrays and column count 1326 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1327 $ save example.mat A b -v7.3 1328 can be directly read by this routine (see Reference 1 for details). 1329 1330 Depending on your MATLAB version, this format might be a default, 1331 otherwise you can set it as default in Preferences. 1332 1333 Unless -nocompression flag is used to save the file in MATLAB, 1334 PETSc must be configured with ZLIB package. 1335 1336 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1337 1338 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1339 1340 Corresponding `MatView()` is not yet implemented. 1341 1342 The loaded matrix is actually a transpose of the original one in MATLAB, 1343 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1344 With this format, matrix is automatically transposed by PETSc, 1345 unless the matrix is marked as SPD or symmetric 1346 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1347 1348 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1349 1350 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1351 @*/ 1352 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1353 { 1354 PetscBool flg; 1355 1356 PetscFunctionBegin; 1357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1358 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1359 1360 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1361 1362 flg = PETSC_FALSE; 1363 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1364 if (flg) { 1365 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1366 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1367 } 1368 flg = PETSC_FALSE; 1369 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1370 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1371 1372 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1373 PetscUseTypeMethod(mat, load, viewer); 1374 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1375 PetscFunctionReturn(PETSC_SUCCESS); 1376 } 1377 1378 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1379 { 1380 Mat_Redundant *redund = *redundant; 1381 1382 PetscFunctionBegin; 1383 if (redund) { 1384 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1385 PetscCall(ISDestroy(&redund->isrow)); 1386 PetscCall(ISDestroy(&redund->iscol)); 1387 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1388 } else { 1389 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1390 PetscCall(PetscFree(redund->sbuf_j)); 1391 PetscCall(PetscFree(redund->sbuf_a)); 1392 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1393 PetscCall(PetscFree(redund->rbuf_j[i])); 1394 PetscCall(PetscFree(redund->rbuf_a[i])); 1395 } 1396 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1397 } 1398 1399 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1400 PetscCall(PetscFree(redund)); 1401 } 1402 PetscFunctionReturn(PETSC_SUCCESS); 1403 } 1404 1405 /*@C 1406 MatDestroy - Frees space taken by a matrix. 1407 1408 Collective 1409 1410 Input Parameter: 1411 . A - the matrix 1412 1413 Level: beginner 1414 1415 Developer Note: 1416 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1417 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1418 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1419 if changes are needed here. 1420 1421 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1422 @*/ 1423 PetscErrorCode MatDestroy(Mat *A) 1424 { 1425 PetscFunctionBegin; 1426 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1427 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1428 if (--((PetscObject)*A)->refct > 0) { 1429 *A = NULL; 1430 PetscFunctionReturn(PETSC_SUCCESS); 1431 } 1432 1433 /* if memory was published with SAWs then destroy it */ 1434 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1435 PetscTryTypeMethod(*A, destroy); 1436 1437 PetscCall(PetscFree((*A)->factorprefix)); 1438 PetscCall(PetscFree((*A)->defaultvectype)); 1439 PetscCall(PetscFree((*A)->defaultrandtype)); 1440 PetscCall(PetscFree((*A)->bsizes)); 1441 PetscCall(PetscFree((*A)->solvertype)); 1442 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1443 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1444 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1445 PetscCall(MatProductClear(*A)); 1446 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1447 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1448 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1449 PetscCall(MatDestroy(&(*A)->schur)); 1450 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1451 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1452 PetscCall(PetscHeaderDestroy(A)); 1453 PetscFunctionReturn(PETSC_SUCCESS); 1454 } 1455 1456 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1457 /*@C 1458 MatSetValues - Inserts or adds a block of values into a matrix. 1459 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1460 MUST be called after all calls to `MatSetValues()` have been completed. 1461 1462 Not Collective 1463 1464 Input Parameters: 1465 + mat - the matrix 1466 . v - a logically two-dimensional array of values 1467 . m - the number of rows 1468 . idxm - the global indices of the rows 1469 . n - the number of columns 1470 . idxn - the global indices of the columns 1471 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1472 1473 Level: beginner 1474 1475 Notes: 1476 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1477 1478 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1479 options cannot be mixed without intervening calls to the assembly 1480 routines. 1481 1482 `MatSetValues()` uses 0-based row and column numbers in Fortran 1483 as well as in C. 1484 1485 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1486 simply ignored. This allows easily inserting element stiffness matrices 1487 with homogeneous Dirichlet boundary conditions that you don't want represented 1488 in the matrix. 1489 1490 Efficiency Alert: 1491 The routine `MatSetValuesBlocked()` may offer much better efficiency 1492 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1493 1494 Developer Note: 1495 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1496 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1497 1498 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1499 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1500 @*/ 1501 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1502 { 1503 PetscFunctionBeginHot; 1504 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1505 PetscValidType(mat, 1); 1506 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1507 PetscAssertPointer(idxm, 3); 1508 PetscAssertPointer(idxn, 5); 1509 MatCheckPreallocated(mat, 1); 1510 1511 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1512 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1513 1514 if (PetscDefined(USE_DEBUG)) { 1515 PetscInt i, j; 1516 1517 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1518 if (v) { 1519 for (i = 0; i < m; i++) { 1520 for (j = 0; j < n; j++) { 1521 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1522 #if defined(PETSC_USE_COMPLEX) 1523 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]); 1524 #else 1525 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]); 1526 #endif 1527 } 1528 } 1529 } 1530 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); 1531 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); 1532 } 1533 1534 if (mat->assembled) { 1535 mat->was_assembled = PETSC_TRUE; 1536 mat->assembled = PETSC_FALSE; 1537 } 1538 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1539 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1540 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1541 PetscFunctionReturn(PETSC_SUCCESS); 1542 } 1543 1544 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1545 /*@ 1546 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1547 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1548 MUST be called after all calls to `MatSetValues()` have been completed. 1549 1550 Not Collective 1551 1552 Input Parameters: 1553 + mat - the matrix 1554 . v - a logically two-dimensional array of values 1555 . ism - the rows to provide 1556 . isn - the columns to provide 1557 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1558 1559 Level: beginner 1560 1561 Notes: 1562 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1563 1564 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1565 options cannot be mixed without intervening calls to the assembly 1566 routines. 1567 1568 `MatSetValues()` uses 0-based row and column numbers in Fortran 1569 as well as in C. 1570 1571 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1572 simply ignored. This allows easily inserting element stiffness matrices 1573 with homogeneous Dirichlet boundary conditions that you don't want represented 1574 in the matrix. 1575 1576 Efficiency Alert: 1577 The routine `MatSetValuesBlocked()` may offer much better efficiency 1578 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1579 1580 This is currently not optimized for any particular `ISType` 1581 1582 Developer Note: 1583 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1584 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1585 1586 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1587 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1588 @*/ 1589 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1590 { 1591 PetscInt m, n; 1592 const PetscInt *rows, *cols; 1593 1594 PetscFunctionBeginHot; 1595 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1596 PetscCall(ISGetIndices(ism, &rows)); 1597 PetscCall(ISGetIndices(isn, &cols)); 1598 PetscCall(ISGetLocalSize(ism, &m)); 1599 PetscCall(ISGetLocalSize(isn, &n)); 1600 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1601 PetscCall(ISRestoreIndices(ism, &rows)); 1602 PetscCall(ISRestoreIndices(isn, &cols)); 1603 PetscFunctionReturn(PETSC_SUCCESS); 1604 } 1605 1606 /*@ 1607 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1608 values into a matrix 1609 1610 Not Collective 1611 1612 Input Parameters: 1613 + mat - the matrix 1614 . row - the (block) row to set 1615 - v - a logically two-dimensional array of values 1616 1617 Level: intermediate 1618 1619 Notes: 1620 The values, `v`, are column-oriented (for the block version) and sorted 1621 1622 All the nonzero values in `row` must be provided 1623 1624 The matrix must have previously had its column indices set, likely by having been assembled. 1625 1626 `row` must belong to this MPI process 1627 1628 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1629 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1630 @*/ 1631 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1632 { 1633 PetscInt globalrow; 1634 1635 PetscFunctionBegin; 1636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1637 PetscValidType(mat, 1); 1638 PetscAssertPointer(v, 3); 1639 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1640 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1641 PetscFunctionReturn(PETSC_SUCCESS); 1642 } 1643 1644 /*@ 1645 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1646 values into a matrix 1647 1648 Not Collective 1649 1650 Input Parameters: 1651 + mat - the matrix 1652 . row - the (block) row to set 1653 - 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 1654 1655 Level: advanced 1656 1657 Notes: 1658 The values, `v`, are column-oriented for the block version. 1659 1660 All the nonzeros in `row` must be provided 1661 1662 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1663 1664 `row` must belong to this process 1665 1666 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1667 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1668 @*/ 1669 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1670 { 1671 PetscFunctionBeginHot; 1672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1673 PetscValidType(mat, 1); 1674 MatCheckPreallocated(mat, 1); 1675 PetscAssertPointer(v, 3); 1676 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1677 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1678 mat->insertmode = INSERT_VALUES; 1679 1680 if (mat->assembled) { 1681 mat->was_assembled = PETSC_TRUE; 1682 mat->assembled = PETSC_FALSE; 1683 } 1684 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1685 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1686 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1687 PetscFunctionReturn(PETSC_SUCCESS); 1688 } 1689 1690 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1691 /*@ 1692 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1693 Using structured grid indexing 1694 1695 Not Collective 1696 1697 Input Parameters: 1698 + mat - the matrix 1699 . m - number of rows being entered 1700 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1701 . n - number of columns being entered 1702 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1703 . v - a logically two-dimensional array of values 1704 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1705 1706 Level: beginner 1707 1708 Notes: 1709 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1710 1711 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1712 options cannot be mixed without intervening calls to the assembly 1713 routines. 1714 1715 The grid coordinates are across the entire grid, not just the local portion 1716 1717 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1718 as well as in C. 1719 1720 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1721 1722 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1723 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1724 1725 The columns and rows in the stencil passed in MUST be contained within the 1726 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1727 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1728 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1729 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1730 1731 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1732 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1733 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1734 `DM_BOUNDARY_PERIODIC` boundary type. 1735 1736 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 1737 a single value per point) you can skip filling those indices. 1738 1739 Inspired by the structured grid interface to the HYPRE package 1740 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1741 1742 Efficiency Alert: 1743 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1744 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1745 1746 Fortran Note: 1747 `idxm` and `idxn` should be declared as 1748 $ MatStencil idxm(4,m),idxn(4,n) 1749 and the values inserted using 1750 .vb 1751 idxm(MatStencil_i,1) = i 1752 idxm(MatStencil_j,1) = j 1753 idxm(MatStencil_k,1) = k 1754 idxm(MatStencil_c,1) = c 1755 etc 1756 .ve 1757 1758 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1759 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1760 @*/ 1761 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1762 { 1763 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1764 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1765 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1766 1767 PetscFunctionBegin; 1768 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1769 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1770 PetscValidType(mat, 1); 1771 PetscAssertPointer(idxm, 3); 1772 PetscAssertPointer(idxn, 5); 1773 1774 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1775 jdxm = buf; 1776 jdxn = buf + m; 1777 } else { 1778 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1779 jdxm = bufm; 1780 jdxn = bufn; 1781 } 1782 for (i = 0; i < m; i++) { 1783 for (j = 0; j < 3 - sdim; j++) dxm++; 1784 tmp = *dxm++ - starts[0]; 1785 for (j = 0; j < dim - 1; j++) { 1786 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1787 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1788 } 1789 if (mat->stencil.noc) dxm++; 1790 jdxm[i] = tmp; 1791 } 1792 for (i = 0; i < n; i++) { 1793 for (j = 0; j < 3 - sdim; j++) dxn++; 1794 tmp = *dxn++ - starts[0]; 1795 for (j = 0; j < dim - 1; j++) { 1796 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1797 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1798 } 1799 if (mat->stencil.noc) dxn++; 1800 jdxn[i] = tmp; 1801 } 1802 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1803 PetscCall(PetscFree2(bufm, bufn)); 1804 PetscFunctionReturn(PETSC_SUCCESS); 1805 } 1806 1807 /*@ 1808 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1809 Using structured grid indexing 1810 1811 Not Collective 1812 1813 Input Parameters: 1814 + mat - the matrix 1815 . m - number of rows being entered 1816 . idxm - grid coordinates for matrix rows being entered 1817 . n - number of columns being entered 1818 . idxn - grid coordinates for matrix columns being entered 1819 . v - a logically two-dimensional array of values 1820 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1821 1822 Level: beginner 1823 1824 Notes: 1825 By default the values, `v`, are row-oriented and unsorted. 1826 See `MatSetOption()` for other options. 1827 1828 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1829 options cannot be mixed without intervening calls to the assembly 1830 routines. 1831 1832 The grid coordinates are across the entire grid, not just the local portion 1833 1834 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1835 as well as in C. 1836 1837 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1838 1839 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1840 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1841 1842 The columns and rows in the stencil passed in MUST be contained within the 1843 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1844 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1845 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1846 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1847 1848 Negative indices may be passed in idxm and idxn, these rows and columns are 1849 simply ignored. This allows easily inserting element stiffness matrices 1850 with homogeneous Dirichlet boundary conditions that you don't want represented 1851 in the matrix. 1852 1853 Inspired by the structured grid interface to the HYPRE package 1854 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1855 1856 Fortran Note: 1857 `idxm` and `idxn` should be declared as 1858 $ MatStencil idxm(4,m),idxn(4,n) 1859 and the values inserted using 1860 .vb 1861 idxm(MatStencil_i,1) = i 1862 idxm(MatStencil_j,1) = j 1863 idxm(MatStencil_k,1) = k 1864 etc 1865 .ve 1866 1867 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1868 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1869 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1870 @*/ 1871 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1872 { 1873 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1874 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1875 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1876 1877 PetscFunctionBegin; 1878 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1880 PetscValidType(mat, 1); 1881 PetscAssertPointer(idxm, 3); 1882 PetscAssertPointer(idxn, 5); 1883 PetscAssertPointer(v, 6); 1884 1885 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1886 jdxm = buf; 1887 jdxn = buf + m; 1888 } else { 1889 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1890 jdxm = bufm; 1891 jdxn = bufn; 1892 } 1893 for (i = 0; i < m; i++) { 1894 for (j = 0; j < 3 - sdim; j++) dxm++; 1895 tmp = *dxm++ - starts[0]; 1896 for (j = 0; j < sdim - 1; j++) { 1897 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1898 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1899 } 1900 dxm++; 1901 jdxm[i] = tmp; 1902 } 1903 for (i = 0; i < n; i++) { 1904 for (j = 0; j < 3 - sdim; j++) dxn++; 1905 tmp = *dxn++ - starts[0]; 1906 for (j = 0; j < sdim - 1; j++) { 1907 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1908 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1909 } 1910 dxn++; 1911 jdxn[i] = tmp; 1912 } 1913 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1914 PetscCall(PetscFree2(bufm, bufn)); 1915 PetscFunctionReturn(PETSC_SUCCESS); 1916 } 1917 1918 /*@ 1919 MatSetStencil - Sets the grid information for setting values into a matrix via 1920 `MatSetValuesStencil()` 1921 1922 Not Collective 1923 1924 Input Parameters: 1925 + mat - the matrix 1926 . dim - dimension of the grid 1, 2, or 3 1927 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1928 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1929 - dof - number of degrees of freedom per node 1930 1931 Level: beginner 1932 1933 Notes: 1934 Inspired by the structured grid interface to the HYPRE package 1935 (www.llnl.gov/CASC/hyper) 1936 1937 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1938 user. 1939 1940 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1941 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1942 @*/ 1943 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1944 { 1945 PetscFunctionBegin; 1946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1947 PetscAssertPointer(dims, 3); 1948 PetscAssertPointer(starts, 4); 1949 1950 mat->stencil.dim = dim + (dof > 1); 1951 for (PetscInt i = 0; i < dim; i++) { 1952 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1953 mat->stencil.starts[i] = starts[dim - i - 1]; 1954 } 1955 mat->stencil.dims[dim] = dof; 1956 mat->stencil.starts[dim] = 0; 1957 mat->stencil.noc = (PetscBool)(dof == 1); 1958 PetscFunctionReturn(PETSC_SUCCESS); 1959 } 1960 1961 /*@C 1962 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1963 1964 Not Collective 1965 1966 Input Parameters: 1967 + mat - the matrix 1968 . v - a logically two-dimensional array of values 1969 . m - the number of block rows 1970 . idxm - the global block indices 1971 . n - the number of block columns 1972 . idxn - the global block indices 1973 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1974 1975 Level: intermediate 1976 1977 Notes: 1978 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1979 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1980 1981 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1982 NOT the total number of rows/columns; for example, if the block size is 2 and 1983 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1984 The values in `idxm` would be 1 2; that is the first index for each block divided by 1985 the block size. 1986 1987 You must call `MatSetBlockSize()` when constructing this matrix (before 1988 preallocating it). 1989 1990 By default the values, `v`, are row-oriented, so the layout of 1991 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1992 1993 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1994 options cannot be mixed without intervening calls to the assembly 1995 routines. 1996 1997 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1998 as well as in C. 1999 2000 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2001 simply ignored. This allows easily inserting element stiffness matrices 2002 with homogeneous Dirichlet boundary conditions that you don't want represented 2003 in the matrix. 2004 2005 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2006 internal searching must be done to determine where to place the 2007 data in the matrix storage space. By instead inserting blocks of 2008 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2009 reduced. 2010 2011 Example: 2012 .vb 2013 Suppose m=n=2 and block size(bs) = 2 The array is 2014 2015 1 2 | 3 4 2016 5 6 | 7 8 2017 - - - | - - - 2018 9 10 | 11 12 2019 13 14 | 15 16 2020 2021 v[] should be passed in like 2022 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2023 2024 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2025 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2026 .ve 2027 2028 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2029 @*/ 2030 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2031 { 2032 PetscFunctionBeginHot; 2033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2034 PetscValidType(mat, 1); 2035 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2036 PetscAssertPointer(idxm, 3); 2037 PetscAssertPointer(idxn, 5); 2038 MatCheckPreallocated(mat, 1); 2039 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2040 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2041 if (PetscDefined(USE_DEBUG)) { 2042 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2043 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2044 } 2045 if (PetscDefined(USE_DEBUG)) { 2046 PetscInt rbs, cbs, M, N, i; 2047 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2048 PetscCall(MatGetSize(mat, &M, &N)); 2049 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M); 2050 for (i = 0; i < n; i++) 2051 PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N); 2052 } 2053 if (mat->assembled) { 2054 mat->was_assembled = PETSC_TRUE; 2055 mat->assembled = PETSC_FALSE; 2056 } 2057 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2058 if (mat->ops->setvaluesblocked) { 2059 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2060 } else { 2061 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2062 PetscInt i, j, bs, cbs; 2063 2064 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2065 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2066 iidxm = buf; 2067 iidxn = buf + m * bs; 2068 } else { 2069 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2070 iidxm = bufr; 2071 iidxn = bufc; 2072 } 2073 for (i = 0; i < m; i++) { 2074 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2075 } 2076 if (m != n || bs != cbs || idxm != idxn) { 2077 for (i = 0; i < n; i++) { 2078 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2079 } 2080 } else iidxn = iidxm; 2081 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2082 PetscCall(PetscFree2(bufr, bufc)); 2083 } 2084 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2085 PetscFunctionReturn(PETSC_SUCCESS); 2086 } 2087 2088 /*@C 2089 MatGetValues - Gets a block of local values from a matrix. 2090 2091 Not Collective; can only return values that are owned by the give process 2092 2093 Input Parameters: 2094 + mat - the matrix 2095 . v - a logically two-dimensional array for storing the values 2096 . m - the number of rows 2097 . idxm - the global indices of the rows 2098 . n - the number of columns 2099 - idxn - the global indices of the columns 2100 2101 Level: advanced 2102 2103 Notes: 2104 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2105 The values, `v`, are then returned in a row-oriented format, 2106 analogous to that used by default in `MatSetValues()`. 2107 2108 `MatGetValues()` uses 0-based row and column numbers in 2109 Fortran as well as in C. 2110 2111 `MatGetValues()` requires that the matrix has been assembled 2112 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2113 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2114 without intermediate matrix assembly. 2115 2116 Negative row or column indices will be ignored and those locations in `v` will be 2117 left unchanged. 2118 2119 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2120 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2121 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2122 2123 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2124 @*/ 2125 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2126 { 2127 PetscFunctionBegin; 2128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2129 PetscValidType(mat, 1); 2130 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2131 PetscAssertPointer(idxm, 3); 2132 PetscAssertPointer(idxn, 5); 2133 PetscAssertPointer(v, 6); 2134 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2135 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2136 MatCheckPreallocated(mat, 1); 2137 2138 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2139 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2140 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@C 2145 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2146 defined previously by `MatSetLocalToGlobalMapping()` 2147 2148 Not Collective 2149 2150 Input Parameters: 2151 + mat - the matrix 2152 . nrow - number of rows 2153 . irow - the row local indices 2154 . ncol - number of columns 2155 - icol - the column local indices 2156 2157 Output Parameter: 2158 . y - a logically two-dimensional array of values 2159 2160 Level: advanced 2161 2162 Notes: 2163 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2164 2165 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, 2166 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2167 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2168 with `MatSetLocalToGlobalMapping()`. 2169 2170 Developer Note: 2171 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2172 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2173 2174 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2175 `MatSetValuesLocal()`, `MatGetValues()` 2176 @*/ 2177 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2178 { 2179 PetscFunctionBeginHot; 2180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2181 PetscValidType(mat, 1); 2182 MatCheckPreallocated(mat, 1); 2183 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2184 PetscAssertPointer(irow, 3); 2185 PetscAssertPointer(icol, 5); 2186 if (PetscDefined(USE_DEBUG)) { 2187 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2188 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2189 } 2190 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2191 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2192 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2193 else { 2194 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2195 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2196 irowm = buf; 2197 icolm = buf + nrow; 2198 } else { 2199 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2200 irowm = bufr; 2201 icolm = bufc; 2202 } 2203 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2204 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2205 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2206 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2207 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2208 PetscCall(PetscFree2(bufr, bufc)); 2209 } 2210 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2211 PetscFunctionReturn(PETSC_SUCCESS); 2212 } 2213 2214 /*@ 2215 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2216 the same size. Currently, this can only be called once and creates the given matrix. 2217 2218 Not Collective 2219 2220 Input Parameters: 2221 + mat - the matrix 2222 . nb - the number of blocks 2223 . bs - the number of rows (and columns) in each block 2224 . rows - a concatenation of the rows for each block 2225 - v - a concatenation of logically two-dimensional arrays of values 2226 2227 Level: advanced 2228 2229 Notes: 2230 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2231 2232 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2233 2234 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2235 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2236 @*/ 2237 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2238 { 2239 PetscFunctionBegin; 2240 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2241 PetscValidType(mat, 1); 2242 PetscAssertPointer(rows, 4); 2243 PetscAssertPointer(v, 5); 2244 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2245 2246 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2247 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2248 else { 2249 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2250 } 2251 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2252 PetscFunctionReturn(PETSC_SUCCESS); 2253 } 2254 2255 /*@ 2256 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2257 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2258 using a local (per-processor) numbering. 2259 2260 Not Collective 2261 2262 Input Parameters: 2263 + x - the matrix 2264 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2265 - cmapping - column mapping 2266 2267 Level: intermediate 2268 2269 Note: 2270 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2271 2272 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2273 @*/ 2274 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2275 { 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2278 PetscValidType(x, 1); 2279 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2280 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2281 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2282 else { 2283 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2284 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2285 } 2286 PetscFunctionReturn(PETSC_SUCCESS); 2287 } 2288 2289 /*@ 2290 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2291 2292 Not Collective 2293 2294 Input Parameter: 2295 . A - the matrix 2296 2297 Output Parameters: 2298 + rmapping - row mapping 2299 - cmapping - column mapping 2300 2301 Level: advanced 2302 2303 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2304 @*/ 2305 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2306 { 2307 PetscFunctionBegin; 2308 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2309 PetscValidType(A, 1); 2310 if (rmapping) { 2311 PetscAssertPointer(rmapping, 2); 2312 *rmapping = A->rmap->mapping; 2313 } 2314 if (cmapping) { 2315 PetscAssertPointer(cmapping, 3); 2316 *cmapping = A->cmap->mapping; 2317 } 2318 PetscFunctionReturn(PETSC_SUCCESS); 2319 } 2320 2321 /*@ 2322 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2323 2324 Logically Collective 2325 2326 Input Parameters: 2327 + A - the matrix 2328 . rmap - row layout 2329 - cmap - column layout 2330 2331 Level: advanced 2332 2333 Note: 2334 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2335 2336 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2337 @*/ 2338 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2339 { 2340 PetscFunctionBegin; 2341 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2342 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2343 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2344 PetscFunctionReturn(PETSC_SUCCESS); 2345 } 2346 2347 /*@ 2348 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2349 2350 Not Collective 2351 2352 Input Parameter: 2353 . A - the matrix 2354 2355 Output Parameters: 2356 + rmap - row layout 2357 - cmap - column layout 2358 2359 Level: advanced 2360 2361 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2362 @*/ 2363 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2364 { 2365 PetscFunctionBegin; 2366 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2367 PetscValidType(A, 1); 2368 if (rmap) { 2369 PetscAssertPointer(rmap, 2); 2370 *rmap = A->rmap; 2371 } 2372 if (cmap) { 2373 PetscAssertPointer(cmap, 3); 2374 *cmap = A->cmap; 2375 } 2376 PetscFunctionReturn(PETSC_SUCCESS); 2377 } 2378 2379 /*@C 2380 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2381 using a local numbering of the rows and columns. 2382 2383 Not Collective 2384 2385 Input Parameters: 2386 + mat - the matrix 2387 . nrow - number of rows 2388 . irow - the row local indices 2389 . ncol - number of columns 2390 . icol - the column local indices 2391 . y - a logically two-dimensional array of values 2392 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2393 2394 Level: intermediate 2395 2396 Notes: 2397 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2398 2399 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2400 options cannot be mixed without intervening calls to the assembly 2401 routines. 2402 2403 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2404 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2405 2406 Developer Note: 2407 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2408 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2409 2410 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2411 `MatGetValuesLocal()` 2412 @*/ 2413 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2414 { 2415 PetscFunctionBeginHot; 2416 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2417 PetscValidType(mat, 1); 2418 MatCheckPreallocated(mat, 1); 2419 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2420 PetscAssertPointer(irow, 3); 2421 PetscAssertPointer(icol, 5); 2422 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2423 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2424 if (PetscDefined(USE_DEBUG)) { 2425 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2426 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2427 } 2428 2429 if (mat->assembled) { 2430 mat->was_assembled = PETSC_TRUE; 2431 mat->assembled = PETSC_FALSE; 2432 } 2433 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2434 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2435 else { 2436 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2437 const PetscInt *irowm, *icolm; 2438 2439 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2440 bufr = buf; 2441 bufc = buf + nrow; 2442 irowm = bufr; 2443 icolm = bufc; 2444 } else { 2445 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2446 irowm = bufr; 2447 icolm = bufc; 2448 } 2449 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2450 else irowm = irow; 2451 if (mat->cmap->mapping) { 2452 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2453 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2454 } else icolm = irowm; 2455 } else icolm = icol; 2456 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2457 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2458 } 2459 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2460 PetscFunctionReturn(PETSC_SUCCESS); 2461 } 2462 2463 /*@C 2464 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2465 using a local ordering of the nodes a block at a time. 2466 2467 Not Collective 2468 2469 Input Parameters: 2470 + mat - the matrix 2471 . nrow - number of rows 2472 . irow - the row local indices 2473 . ncol - number of columns 2474 . icol - the column local indices 2475 . y - a logically two-dimensional array of values 2476 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2477 2478 Level: intermediate 2479 2480 Notes: 2481 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2482 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2483 2484 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2485 options cannot be mixed without intervening calls to the assembly 2486 routines. 2487 2488 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2489 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2490 2491 Developer Note: 2492 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2493 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2494 2495 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2496 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2497 @*/ 2498 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2499 { 2500 PetscFunctionBeginHot; 2501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2502 PetscValidType(mat, 1); 2503 MatCheckPreallocated(mat, 1); 2504 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2505 PetscAssertPointer(irow, 3); 2506 PetscAssertPointer(icol, 5); 2507 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2508 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2509 if (PetscDefined(USE_DEBUG)) { 2510 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2511 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); 2512 } 2513 2514 if (mat->assembled) { 2515 mat->was_assembled = PETSC_TRUE; 2516 mat->assembled = PETSC_FALSE; 2517 } 2518 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2519 PetscInt irbs, rbs; 2520 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2521 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2522 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2523 } 2524 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2525 PetscInt icbs, cbs; 2526 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2527 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2528 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2529 } 2530 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2531 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2532 else { 2533 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2534 const PetscInt *irowm, *icolm; 2535 2536 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2537 bufr = buf; 2538 bufc = buf + nrow; 2539 irowm = bufr; 2540 icolm = bufc; 2541 } else { 2542 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2543 irowm = bufr; 2544 icolm = bufc; 2545 } 2546 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2547 else irowm = irow; 2548 if (mat->cmap->mapping) { 2549 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2550 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2551 } else icolm = irowm; 2552 } else icolm = icol; 2553 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2554 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2555 } 2556 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2557 PetscFunctionReturn(PETSC_SUCCESS); 2558 } 2559 2560 /*@ 2561 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2562 2563 Collective 2564 2565 Input Parameters: 2566 + mat - the matrix 2567 - x - the vector to be multiplied 2568 2569 Output Parameter: 2570 . y - the result 2571 2572 Level: developer 2573 2574 Note: 2575 The vectors `x` and `y` cannot be the same. I.e., one cannot 2576 call `MatMultDiagonalBlock`(A,y,y). 2577 2578 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2579 @*/ 2580 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2581 { 2582 PetscFunctionBegin; 2583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2584 PetscValidType(mat, 1); 2585 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2586 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2587 2588 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2589 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2590 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2591 MatCheckPreallocated(mat, 1); 2592 2593 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2594 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2595 PetscFunctionReturn(PETSC_SUCCESS); 2596 } 2597 2598 /*@ 2599 MatMult - Computes the matrix-vector product, $y = Ax$. 2600 2601 Neighbor-wise Collective 2602 2603 Input Parameters: 2604 + mat - the matrix 2605 - x - the vector to be multiplied 2606 2607 Output Parameter: 2608 . y - the result 2609 2610 Level: beginner 2611 2612 Note: 2613 The vectors `x` and `y` cannot be the same. I.e., one cannot 2614 call `MatMult`(A,y,y). 2615 2616 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2617 @*/ 2618 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2619 { 2620 PetscFunctionBegin; 2621 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2622 PetscValidType(mat, 1); 2623 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2624 VecCheckAssembled(x); 2625 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2627 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2628 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2629 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); 2630 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); 2631 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); 2632 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); 2633 PetscCall(VecSetErrorIfLocked(y, 3)); 2634 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2635 MatCheckPreallocated(mat, 1); 2636 2637 PetscCall(VecLockReadPush(x)); 2638 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2639 PetscUseTypeMethod(mat, mult, x, y); 2640 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2641 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2642 PetscCall(VecLockReadPop(x)); 2643 PetscFunctionReturn(PETSC_SUCCESS); 2644 } 2645 2646 /*@ 2647 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2648 2649 Neighbor-wise Collective 2650 2651 Input Parameters: 2652 + mat - the matrix 2653 - x - the vector to be multiplied 2654 2655 Output Parameter: 2656 . y - the result 2657 2658 Level: beginner 2659 2660 Notes: 2661 The vectors `x` and `y` cannot be the same. I.e., one cannot 2662 call `MatMultTranspose`(A,y,y). 2663 2664 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2665 use `MatMultHermitianTranspose()` 2666 2667 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2668 @*/ 2669 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2670 { 2671 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2672 2673 PetscFunctionBegin; 2674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2675 PetscValidType(mat, 1); 2676 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2677 VecCheckAssembled(x); 2678 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2679 2680 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2681 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2682 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2683 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); 2684 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); 2685 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); 2686 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); 2687 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2688 MatCheckPreallocated(mat, 1); 2689 2690 if (!mat->ops->multtranspose) { 2691 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2692 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); 2693 } else op = mat->ops->multtranspose; 2694 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2695 PetscCall(VecLockReadPush(x)); 2696 PetscCall((*op)(mat, x, y)); 2697 PetscCall(VecLockReadPop(x)); 2698 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2699 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2700 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2701 PetscFunctionReturn(PETSC_SUCCESS); 2702 } 2703 2704 /*@ 2705 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2706 2707 Neighbor-wise Collective 2708 2709 Input Parameters: 2710 + mat - the matrix 2711 - x - the vector to be multiplied 2712 2713 Output Parameter: 2714 . y - the result 2715 2716 Level: beginner 2717 2718 Notes: 2719 The vectors `x` and `y` cannot be the same. I.e., one cannot 2720 call `MatMultHermitianTranspose`(A,y,y). 2721 2722 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2723 2724 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2725 2726 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2727 @*/ 2728 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2729 { 2730 PetscFunctionBegin; 2731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2732 PetscValidType(mat, 1); 2733 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2734 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2735 2736 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2737 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2738 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2739 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); 2740 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); 2741 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); 2742 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); 2743 MatCheckPreallocated(mat, 1); 2744 2745 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2746 #if defined(PETSC_USE_COMPLEX) 2747 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2748 PetscCall(VecLockReadPush(x)); 2749 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2750 else PetscUseTypeMethod(mat, mult, x, y); 2751 PetscCall(VecLockReadPop(x)); 2752 } else { 2753 Vec w; 2754 PetscCall(VecDuplicate(x, &w)); 2755 PetscCall(VecCopy(x, w)); 2756 PetscCall(VecConjugate(w)); 2757 PetscCall(MatMultTranspose(mat, w, y)); 2758 PetscCall(VecDestroy(&w)); 2759 PetscCall(VecConjugate(y)); 2760 } 2761 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2762 #else 2763 PetscCall(MatMultTranspose(mat, x, y)); 2764 #endif 2765 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2766 PetscFunctionReturn(PETSC_SUCCESS); 2767 } 2768 2769 /*@ 2770 MatMultAdd - Computes $v3 = v2 + A * v1$. 2771 2772 Neighbor-wise Collective 2773 2774 Input Parameters: 2775 + mat - the matrix 2776 . v1 - the vector to be multiplied by `mat` 2777 - v2 - the vector to be added to the result 2778 2779 Output Parameter: 2780 . v3 - the result 2781 2782 Level: beginner 2783 2784 Note: 2785 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2786 call `MatMultAdd`(A,v1,v2,v1). 2787 2788 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2789 @*/ 2790 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2791 { 2792 PetscFunctionBegin; 2793 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2794 PetscValidType(mat, 1); 2795 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2796 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2797 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2798 2799 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2800 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2801 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); 2802 /* 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); 2803 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); */ 2804 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); 2805 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); 2806 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2807 MatCheckPreallocated(mat, 1); 2808 2809 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2810 PetscCall(VecLockReadPush(v1)); 2811 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2812 PetscCall(VecLockReadPop(v1)); 2813 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2814 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2815 PetscFunctionReturn(PETSC_SUCCESS); 2816 } 2817 2818 /*@ 2819 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2820 2821 Neighbor-wise Collective 2822 2823 Input Parameters: 2824 + mat - the matrix 2825 . v1 - the vector to be multiplied by the transpose of the matrix 2826 - v2 - the vector to be added to the result 2827 2828 Output Parameter: 2829 . v3 - the result 2830 2831 Level: beginner 2832 2833 Note: 2834 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2835 call `MatMultTransposeAdd`(A,v1,v2,v1). 2836 2837 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2838 @*/ 2839 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2840 { 2841 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2842 2843 PetscFunctionBegin; 2844 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2845 PetscValidType(mat, 1); 2846 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2847 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2848 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2849 2850 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2851 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2852 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); 2853 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); 2854 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); 2855 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2856 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2857 MatCheckPreallocated(mat, 1); 2858 2859 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2860 PetscCall(VecLockReadPush(v1)); 2861 PetscCall((*op)(mat, v1, v2, v3)); 2862 PetscCall(VecLockReadPop(v1)); 2863 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2864 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2865 PetscFunctionReturn(PETSC_SUCCESS); 2866 } 2867 2868 /*@ 2869 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2870 2871 Neighbor-wise Collective 2872 2873 Input Parameters: 2874 + mat - the matrix 2875 . v1 - the vector to be multiplied by the Hermitian transpose 2876 - v2 - the vector to be added to the result 2877 2878 Output Parameter: 2879 . v3 - the result 2880 2881 Level: beginner 2882 2883 Note: 2884 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2885 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2886 2887 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2888 @*/ 2889 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2890 { 2891 PetscFunctionBegin; 2892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2893 PetscValidType(mat, 1); 2894 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2895 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2896 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2897 2898 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2899 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2900 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2901 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); 2902 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); 2903 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); 2904 MatCheckPreallocated(mat, 1); 2905 2906 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2907 PetscCall(VecLockReadPush(v1)); 2908 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2909 else { 2910 Vec w, z; 2911 PetscCall(VecDuplicate(v1, &w)); 2912 PetscCall(VecCopy(v1, w)); 2913 PetscCall(VecConjugate(w)); 2914 PetscCall(VecDuplicate(v3, &z)); 2915 PetscCall(MatMultTranspose(mat, w, z)); 2916 PetscCall(VecDestroy(&w)); 2917 PetscCall(VecConjugate(z)); 2918 if (v2 != v3) { 2919 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2920 } else { 2921 PetscCall(VecAXPY(v3, 1.0, z)); 2922 } 2923 PetscCall(VecDestroy(&z)); 2924 } 2925 PetscCall(VecLockReadPop(v1)); 2926 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2927 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2928 PetscFunctionReturn(PETSC_SUCCESS); 2929 } 2930 2931 /*@ 2932 MatGetFactorType - gets the type of factorization a matrix is 2933 2934 Not Collective 2935 2936 Input Parameter: 2937 . mat - the matrix 2938 2939 Output Parameter: 2940 . 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` 2941 2942 Level: intermediate 2943 2944 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2945 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2946 @*/ 2947 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2948 { 2949 PetscFunctionBegin; 2950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2951 PetscValidType(mat, 1); 2952 PetscAssertPointer(t, 2); 2953 *t = mat->factortype; 2954 PetscFunctionReturn(PETSC_SUCCESS); 2955 } 2956 2957 /*@ 2958 MatSetFactorType - sets the type of factorization a matrix is 2959 2960 Logically Collective 2961 2962 Input Parameters: 2963 + mat - the matrix 2964 - 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` 2965 2966 Level: intermediate 2967 2968 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2969 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2970 @*/ 2971 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2972 { 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2975 PetscValidType(mat, 1); 2976 mat->factortype = t; 2977 PetscFunctionReturn(PETSC_SUCCESS); 2978 } 2979 2980 /*@C 2981 MatGetInfo - Returns information about matrix storage (number of 2982 nonzeros, memory, etc.). 2983 2984 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2985 2986 Input Parameters: 2987 + mat - the matrix 2988 - 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) 2989 2990 Output Parameter: 2991 . info - matrix information context 2992 2993 Options Database Key: 2994 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2995 2996 Notes: 2997 The `MatInfo` context contains a variety of matrix data, including 2998 number of nonzeros allocated and used, number of mallocs during 2999 matrix assembly, etc. Additional information for factored matrices 3000 is provided (such as the fill ratio, number of mallocs during 3001 factorization, etc.). 3002 3003 Example: 3004 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3005 data within the MatInfo context. For example, 3006 .vb 3007 MatInfo info; 3008 Mat A; 3009 double mal, nz_a, nz_u; 3010 3011 MatGetInfo(A, MAT_LOCAL, &info); 3012 mal = info.mallocs; 3013 nz_a = info.nz_allocated; 3014 .ve 3015 3016 Fortran users should declare info as a double precision 3017 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3018 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3019 a complete list of parameter names. 3020 .vb 3021 double precision info(MAT_INFO_SIZE) 3022 double precision mal, nz_a 3023 Mat A 3024 integer ierr 3025 3026 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3027 mal = info(MAT_INFO_MALLOCS) 3028 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3029 .ve 3030 3031 Level: intermediate 3032 3033 Developer Note: 3034 The Fortran interface is not autogenerated as the 3035 interface definition cannot be generated correctly [due to `MatInfo` argument] 3036 3037 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3038 @*/ 3039 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3040 { 3041 PetscFunctionBegin; 3042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3043 PetscValidType(mat, 1); 3044 PetscAssertPointer(info, 3); 3045 MatCheckPreallocated(mat, 1); 3046 PetscUseTypeMethod(mat, getinfo, flag, info); 3047 PetscFunctionReturn(PETSC_SUCCESS); 3048 } 3049 3050 /* 3051 This is used by external packages where it is not easy to get the info from the actual 3052 matrix factorization. 3053 */ 3054 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3055 { 3056 PetscFunctionBegin; 3057 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3058 PetscFunctionReturn(PETSC_SUCCESS); 3059 } 3060 3061 /*@C 3062 MatLUFactor - Performs in-place LU factorization of matrix. 3063 3064 Collective 3065 3066 Input Parameters: 3067 + mat - the matrix 3068 . row - row permutation 3069 . col - column permutation 3070 - info - options for factorization, includes 3071 .vb 3072 fill - expected fill as ratio of original fill. 3073 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3074 Run with the option -info to determine an optimal value to use 3075 .ve 3076 3077 Level: developer 3078 3079 Notes: 3080 Most users should employ the `KSP` interface for linear solvers 3081 instead of working directly with matrix algebra routines such as this. 3082 See, e.g., `KSPCreate()`. 3083 3084 This changes the state of the matrix to a factored matrix; it cannot be used 3085 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3086 3087 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3088 when not using `KSP`. 3089 3090 Developer Note: 3091 The Fortran interface is not autogenerated as the 3092 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3093 3094 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3095 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3096 @*/ 3097 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3098 { 3099 MatFactorInfo tinfo; 3100 3101 PetscFunctionBegin; 3102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3103 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3104 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3105 if (info) PetscAssertPointer(info, 4); 3106 PetscValidType(mat, 1); 3107 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3108 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3109 MatCheckPreallocated(mat, 1); 3110 if (!info) { 3111 PetscCall(MatFactorInfoInitialize(&tinfo)); 3112 info = &tinfo; 3113 } 3114 3115 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3116 PetscUseTypeMethod(mat, lufactor, row, col, info); 3117 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3118 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3119 PetscFunctionReturn(PETSC_SUCCESS); 3120 } 3121 3122 /*@C 3123 MatILUFactor - Performs in-place ILU factorization of matrix. 3124 3125 Collective 3126 3127 Input Parameters: 3128 + mat - the matrix 3129 . row - row permutation 3130 . col - column permutation 3131 - info - structure containing 3132 .vb 3133 levels - number of levels of fill. 3134 expected fill - as ratio of original fill. 3135 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3136 missing diagonal entries) 3137 .ve 3138 3139 Level: developer 3140 3141 Notes: 3142 Most users should employ the `KSP` interface for linear solvers 3143 instead of working directly with matrix algebra routines such as this. 3144 See, e.g., `KSPCreate()`. 3145 3146 Probably really in-place only when level of fill is zero, otherwise allocates 3147 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3148 when not using `KSP`. 3149 3150 Developer Note: 3151 The Fortran interface is not autogenerated as the 3152 interface definition cannot be generated correctly [due to MatFactorInfo] 3153 3154 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3155 @*/ 3156 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3157 { 3158 PetscFunctionBegin; 3159 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3160 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3161 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3162 PetscAssertPointer(info, 4); 3163 PetscValidType(mat, 1); 3164 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3165 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3166 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3167 MatCheckPreallocated(mat, 1); 3168 3169 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3170 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3171 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3172 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3173 PetscFunctionReturn(PETSC_SUCCESS); 3174 } 3175 3176 /*@C 3177 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3178 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3179 3180 Collective 3181 3182 Input Parameters: 3183 + fact - the factor matrix obtained with `MatGetFactor()` 3184 . mat - the matrix 3185 . row - the row permutation 3186 . col - the column permutation 3187 - info - options for factorization, includes 3188 .vb 3189 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3190 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3191 .ve 3192 3193 Level: developer 3194 3195 Notes: 3196 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3197 3198 Most users should employ the simplified `KSP` interface for linear solvers 3199 instead of working directly with matrix algebra routines such as this. 3200 See, e.g., `KSPCreate()`. 3201 3202 Developer Note: 3203 The Fortran interface is not autogenerated as the 3204 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3205 3206 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3207 @*/ 3208 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3209 { 3210 MatFactorInfo tinfo; 3211 3212 PetscFunctionBegin; 3213 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3215 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3216 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3217 if (info) PetscAssertPointer(info, 5); 3218 PetscValidType(fact, 1); 3219 PetscValidType(mat, 2); 3220 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3221 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3222 MatCheckPreallocated(mat, 2); 3223 if (!info) { 3224 PetscCall(MatFactorInfoInitialize(&tinfo)); 3225 info = &tinfo; 3226 } 3227 3228 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3229 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3230 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3231 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3232 PetscFunctionReturn(PETSC_SUCCESS); 3233 } 3234 3235 /*@C 3236 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3237 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3238 3239 Collective 3240 3241 Input Parameters: 3242 + fact - the factor matrix obtained with `MatGetFactor()` 3243 . mat - the matrix 3244 - info - options for factorization 3245 3246 Level: developer 3247 3248 Notes: 3249 See `MatLUFactor()` for in-place factorization. See 3250 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3251 3252 Most users should employ the `KSP` interface for linear solvers 3253 instead of working directly with matrix algebra routines such as this. 3254 See, e.g., `KSPCreate()`. 3255 3256 Developer Note: 3257 The Fortran interface is not autogenerated as the 3258 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3259 3260 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3261 @*/ 3262 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3263 { 3264 MatFactorInfo tinfo; 3265 3266 PetscFunctionBegin; 3267 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3268 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3269 PetscValidType(fact, 1); 3270 PetscValidType(mat, 2); 3271 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3272 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, 3273 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3274 3275 MatCheckPreallocated(mat, 2); 3276 if (!info) { 3277 PetscCall(MatFactorInfoInitialize(&tinfo)); 3278 info = &tinfo; 3279 } 3280 3281 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3282 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3283 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3284 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3285 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3286 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3287 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3288 PetscFunctionReturn(PETSC_SUCCESS); 3289 } 3290 3291 /*@C 3292 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3293 symmetric matrix. 3294 3295 Collective 3296 3297 Input Parameters: 3298 + mat - the matrix 3299 . perm - row and column permutations 3300 - info - expected fill as ratio of original fill 3301 3302 Level: developer 3303 3304 Notes: 3305 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3306 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3307 3308 Most users should employ the `KSP` interface for linear solvers 3309 instead of working directly with matrix algebra routines such as this. 3310 See, e.g., `KSPCreate()`. 3311 3312 Developer Note: 3313 The Fortran interface is not autogenerated as the 3314 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3315 3316 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3317 `MatGetOrdering()` 3318 @*/ 3319 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3320 { 3321 MatFactorInfo tinfo; 3322 3323 PetscFunctionBegin; 3324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3325 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3326 if (info) PetscAssertPointer(info, 3); 3327 PetscValidType(mat, 1); 3328 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3329 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3330 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3331 MatCheckPreallocated(mat, 1); 3332 if (!info) { 3333 PetscCall(MatFactorInfoInitialize(&tinfo)); 3334 info = &tinfo; 3335 } 3336 3337 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3338 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3339 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3340 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3341 PetscFunctionReturn(PETSC_SUCCESS); 3342 } 3343 3344 /*@C 3345 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3346 of a symmetric matrix. 3347 3348 Collective 3349 3350 Input Parameters: 3351 + fact - the factor matrix obtained with `MatGetFactor()` 3352 . mat - the matrix 3353 . perm - row and column permutations 3354 - info - options for factorization, includes 3355 .vb 3356 fill - expected fill as ratio of original fill. 3357 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3358 Run with the option -info to determine an optimal value to use 3359 .ve 3360 3361 Level: developer 3362 3363 Notes: 3364 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3365 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3366 3367 Most users should employ the `KSP` interface for linear solvers 3368 instead of working directly with matrix algebra routines such as this. 3369 See, e.g., `KSPCreate()`. 3370 3371 Developer Note: 3372 The Fortran interface is not autogenerated as the 3373 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3374 3375 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3376 `MatGetOrdering()` 3377 @*/ 3378 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3379 { 3380 MatFactorInfo tinfo; 3381 3382 PetscFunctionBegin; 3383 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3384 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3385 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3386 if (info) PetscAssertPointer(info, 4); 3387 PetscValidType(fact, 1); 3388 PetscValidType(mat, 2); 3389 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3390 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3391 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3392 MatCheckPreallocated(mat, 2); 3393 if (!info) { 3394 PetscCall(MatFactorInfoInitialize(&tinfo)); 3395 info = &tinfo; 3396 } 3397 3398 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3399 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3400 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3401 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3402 PetscFunctionReturn(PETSC_SUCCESS); 3403 } 3404 3405 /*@C 3406 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3407 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3408 `MatCholeskyFactorSymbolic()`. 3409 3410 Collective 3411 3412 Input Parameters: 3413 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3414 . mat - the initial matrix that is to be factored 3415 - info - options for factorization 3416 3417 Level: developer 3418 3419 Note: 3420 Most users should employ the `KSP` interface for linear solvers 3421 instead of working directly with matrix algebra routines such as this. 3422 See, e.g., `KSPCreate()`. 3423 3424 Developer Note: 3425 The Fortran interface is not autogenerated as the 3426 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3427 3428 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3429 @*/ 3430 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3431 { 3432 MatFactorInfo tinfo; 3433 3434 PetscFunctionBegin; 3435 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3437 PetscValidType(fact, 1); 3438 PetscValidType(mat, 2); 3439 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3440 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, 3441 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3442 MatCheckPreallocated(mat, 2); 3443 if (!info) { 3444 PetscCall(MatFactorInfoInitialize(&tinfo)); 3445 info = &tinfo; 3446 } 3447 3448 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3449 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3450 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3451 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3452 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3453 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3454 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3455 PetscFunctionReturn(PETSC_SUCCESS); 3456 } 3457 3458 /*@ 3459 MatQRFactor - Performs in-place QR factorization of matrix. 3460 3461 Collective 3462 3463 Input Parameters: 3464 + mat - the matrix 3465 . col - column permutation 3466 - info - options for factorization, includes 3467 .vb 3468 fill - expected fill as ratio of original fill. 3469 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3470 Run with the option -info to determine an optimal value to use 3471 .ve 3472 3473 Level: developer 3474 3475 Notes: 3476 Most users should employ the `KSP` interface for linear solvers 3477 instead of working directly with matrix algebra routines such as this. 3478 See, e.g., `KSPCreate()`. 3479 3480 This changes the state of the matrix to a factored matrix; it cannot be used 3481 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3482 3483 Developer Note: 3484 The Fortran interface is not autogenerated as the 3485 interface definition cannot be generated correctly [due to MatFactorInfo] 3486 3487 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3488 `MatSetUnfactored()` 3489 @*/ 3490 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3491 { 3492 PetscFunctionBegin; 3493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3494 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3495 if (info) PetscAssertPointer(info, 3); 3496 PetscValidType(mat, 1); 3497 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3498 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3499 MatCheckPreallocated(mat, 1); 3500 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3501 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3502 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3503 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3504 PetscFunctionReturn(PETSC_SUCCESS); 3505 } 3506 3507 /*@ 3508 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3509 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3510 3511 Collective 3512 3513 Input Parameters: 3514 + fact - the factor matrix obtained with `MatGetFactor()` 3515 . mat - the matrix 3516 . col - column permutation 3517 - info - options for factorization, includes 3518 .vb 3519 fill - expected fill as ratio of original fill. 3520 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3521 Run with the option -info to determine an optimal value to use 3522 .ve 3523 3524 Level: developer 3525 3526 Note: 3527 Most users should employ the `KSP` interface for linear solvers 3528 instead of working directly with matrix algebra routines such as this. 3529 See, e.g., `KSPCreate()`. 3530 3531 Developer Note: 3532 The Fortran interface is not autogenerated as the 3533 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3534 3535 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3536 @*/ 3537 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3538 { 3539 MatFactorInfo tinfo; 3540 3541 PetscFunctionBegin; 3542 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3544 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3545 if (info) PetscAssertPointer(info, 4); 3546 PetscValidType(fact, 1); 3547 PetscValidType(mat, 2); 3548 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3549 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3550 MatCheckPreallocated(mat, 2); 3551 if (!info) { 3552 PetscCall(MatFactorInfoInitialize(&tinfo)); 3553 info = &tinfo; 3554 } 3555 3556 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3557 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3558 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3559 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3560 PetscFunctionReturn(PETSC_SUCCESS); 3561 } 3562 3563 /*@ 3564 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3565 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3566 3567 Collective 3568 3569 Input Parameters: 3570 + fact - the factor matrix obtained with `MatGetFactor()` 3571 . mat - the matrix 3572 - info - options for factorization 3573 3574 Level: developer 3575 3576 Notes: 3577 See `MatQRFactor()` for in-place factorization. 3578 3579 Most users should employ the `KSP` interface for linear solvers 3580 instead of working directly with matrix algebra routines such as this. 3581 See, e.g., `KSPCreate()`. 3582 3583 Developer Note: 3584 The Fortran interface is not autogenerated as the 3585 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3586 3587 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3588 @*/ 3589 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3590 { 3591 MatFactorInfo tinfo; 3592 3593 PetscFunctionBegin; 3594 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3595 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3596 PetscValidType(fact, 1); 3597 PetscValidType(mat, 2); 3598 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3599 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, 3600 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3601 3602 MatCheckPreallocated(mat, 2); 3603 if (!info) { 3604 PetscCall(MatFactorInfoInitialize(&tinfo)); 3605 info = &tinfo; 3606 } 3607 3608 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3609 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3610 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3611 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3612 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3613 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3614 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3615 PetscFunctionReturn(PETSC_SUCCESS); 3616 } 3617 3618 /*@ 3619 MatSolve - Solves $A x = b$, given a factored matrix. 3620 3621 Neighbor-wise Collective 3622 3623 Input Parameters: 3624 + mat - the factored matrix 3625 - b - the right-hand-side vector 3626 3627 Output Parameter: 3628 . x - the result vector 3629 3630 Level: developer 3631 3632 Notes: 3633 The vectors `b` and `x` cannot be the same. I.e., one cannot 3634 call `MatSolve`(A,x,x). 3635 3636 Most users should employ the `KSP` interface for linear solvers 3637 instead of working directly with matrix algebra routines such as this. 3638 See, e.g., `KSPCreate()`. 3639 3640 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3641 @*/ 3642 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3643 { 3644 PetscFunctionBegin; 3645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3646 PetscValidType(mat, 1); 3647 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3648 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3649 PetscCheckSameComm(mat, 1, b, 2); 3650 PetscCheckSameComm(mat, 1, x, 3); 3651 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3652 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); 3653 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); 3654 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); 3655 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3656 MatCheckPreallocated(mat, 1); 3657 3658 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3659 if (mat->factorerrortype) { 3660 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3661 PetscCall(VecSetInf(x)); 3662 } else PetscUseTypeMethod(mat, solve, b, x); 3663 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3664 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3665 PetscFunctionReturn(PETSC_SUCCESS); 3666 } 3667 3668 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3669 { 3670 Vec b, x; 3671 PetscInt N, i; 3672 PetscErrorCode (*f)(Mat, Vec, Vec); 3673 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3674 3675 PetscFunctionBegin; 3676 if (A->factorerrortype) { 3677 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3678 PetscCall(MatSetInf(X)); 3679 PetscFunctionReturn(PETSC_SUCCESS); 3680 } 3681 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3682 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3683 PetscCall(MatBoundToCPU(A, &Abound)); 3684 if (!Abound) { 3685 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3686 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3687 } 3688 #if PetscDefined(HAVE_CUDA) 3689 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3690 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3691 #elif PetscDefined(HAVE_HIP) 3692 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3693 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3694 #endif 3695 PetscCall(MatGetSize(B, NULL, &N)); 3696 for (i = 0; i < N; i++) { 3697 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3698 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3699 PetscCall((*f)(A, b, x)); 3700 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3701 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3702 } 3703 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3704 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3705 PetscFunctionReturn(PETSC_SUCCESS); 3706 } 3707 3708 /*@ 3709 MatMatSolve - Solves $A X = B$, given a factored matrix. 3710 3711 Neighbor-wise Collective 3712 3713 Input Parameters: 3714 + A - the factored matrix 3715 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3716 3717 Output Parameter: 3718 . X - the result matrix (dense matrix) 3719 3720 Level: developer 3721 3722 Note: 3723 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3724 otherwise, `B` and `X` cannot be the same. 3725 3726 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3727 @*/ 3728 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3729 { 3730 PetscFunctionBegin; 3731 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3732 PetscValidType(A, 1); 3733 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3734 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3735 PetscCheckSameComm(A, 1, B, 2); 3736 PetscCheckSameComm(A, 1, X, 3); 3737 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); 3738 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); 3739 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"); 3740 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3741 MatCheckPreallocated(A, 1); 3742 3743 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3744 if (!A->ops->matsolve) { 3745 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3746 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3747 } else PetscUseTypeMethod(A, matsolve, B, X); 3748 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3749 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3750 PetscFunctionReturn(PETSC_SUCCESS); 3751 } 3752 3753 /*@ 3754 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3755 3756 Neighbor-wise Collective 3757 3758 Input Parameters: 3759 + A - the factored matrix 3760 - B - the right-hand-side matrix (`MATDENSE` matrix) 3761 3762 Output Parameter: 3763 . X - the result matrix (dense matrix) 3764 3765 Level: developer 3766 3767 Note: 3768 The matrices `B` and `X` cannot be the same. I.e., one cannot 3769 call `MatMatSolveTranspose`(A,X,X). 3770 3771 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3772 @*/ 3773 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3774 { 3775 PetscFunctionBegin; 3776 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3777 PetscValidType(A, 1); 3778 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3779 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3780 PetscCheckSameComm(A, 1, B, 2); 3781 PetscCheckSameComm(A, 1, X, 3); 3782 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3783 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); 3784 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); 3785 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); 3786 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"); 3787 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3788 MatCheckPreallocated(A, 1); 3789 3790 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3791 if (!A->ops->matsolvetranspose) { 3792 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3793 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3794 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3795 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3796 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3797 PetscFunctionReturn(PETSC_SUCCESS); 3798 } 3799 3800 /*@ 3801 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3802 3803 Neighbor-wise Collective 3804 3805 Input Parameters: 3806 + A - the factored matrix 3807 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3808 3809 Output Parameter: 3810 . X - the result matrix (dense matrix) 3811 3812 Level: developer 3813 3814 Note: 3815 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 3816 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3817 3818 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3819 @*/ 3820 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3821 { 3822 PetscFunctionBegin; 3823 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3824 PetscValidType(A, 1); 3825 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3826 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3827 PetscCheckSameComm(A, 1, Bt, 2); 3828 PetscCheckSameComm(A, 1, X, 3); 3829 3830 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3831 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); 3832 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); 3833 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"); 3834 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3835 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3836 MatCheckPreallocated(A, 1); 3837 3838 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3839 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3840 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3841 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3842 PetscFunctionReturn(PETSC_SUCCESS); 3843 } 3844 3845 /*@ 3846 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3847 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3848 3849 Neighbor-wise Collective 3850 3851 Input Parameters: 3852 + mat - the factored matrix 3853 - b - the right-hand-side vector 3854 3855 Output Parameter: 3856 . x - the result vector 3857 3858 Level: developer 3859 3860 Notes: 3861 `MatSolve()` should be used for most applications, as it performs 3862 a forward solve followed by a backward solve. 3863 3864 The vectors `b` and `x` cannot be the same, i.e., one cannot 3865 call `MatForwardSolve`(A,x,x). 3866 3867 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3868 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3869 `MatForwardSolve()` solves $U^T*D y = b$, and 3870 `MatBackwardSolve()` solves $U x = y$. 3871 Thus they do not provide a symmetric preconditioner. 3872 3873 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3874 @*/ 3875 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3876 { 3877 PetscFunctionBegin; 3878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3879 PetscValidType(mat, 1); 3880 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3881 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3882 PetscCheckSameComm(mat, 1, b, 2); 3883 PetscCheckSameComm(mat, 1, x, 3); 3884 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3885 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); 3886 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); 3887 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); 3888 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3889 MatCheckPreallocated(mat, 1); 3890 3891 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3892 PetscUseTypeMethod(mat, forwardsolve, b, x); 3893 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3894 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3895 PetscFunctionReturn(PETSC_SUCCESS); 3896 } 3897 3898 /*@ 3899 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3900 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3901 3902 Neighbor-wise Collective 3903 3904 Input Parameters: 3905 + mat - the factored matrix 3906 - b - the right-hand-side vector 3907 3908 Output Parameter: 3909 . x - the result vector 3910 3911 Level: developer 3912 3913 Notes: 3914 `MatSolve()` should be used for most applications, as it performs 3915 a forward solve followed by a backward solve. 3916 3917 The vectors `b` and `x` cannot be the same. I.e., one cannot 3918 call `MatBackwardSolve`(A,x,x). 3919 3920 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3921 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3922 `MatForwardSolve()` solves $U^T*D y = b$, and 3923 `MatBackwardSolve()` solves $U x = y$. 3924 Thus they do not provide a symmetric preconditioner. 3925 3926 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3927 @*/ 3928 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3929 { 3930 PetscFunctionBegin; 3931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3932 PetscValidType(mat, 1); 3933 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3934 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3935 PetscCheckSameComm(mat, 1, b, 2); 3936 PetscCheckSameComm(mat, 1, x, 3); 3937 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3938 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); 3939 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); 3940 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); 3941 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3942 MatCheckPreallocated(mat, 1); 3943 3944 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3945 PetscUseTypeMethod(mat, backwardsolve, b, x); 3946 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3947 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3948 PetscFunctionReturn(PETSC_SUCCESS); 3949 } 3950 3951 /*@ 3952 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3953 3954 Neighbor-wise Collective 3955 3956 Input Parameters: 3957 + mat - the factored matrix 3958 . b - the right-hand-side vector 3959 - y - the vector to be added to 3960 3961 Output Parameter: 3962 . x - the result vector 3963 3964 Level: developer 3965 3966 Note: 3967 The vectors `b` and `x` cannot be the same. I.e., one cannot 3968 call `MatSolveAdd`(A,x,y,x). 3969 3970 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3971 @*/ 3972 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3973 { 3974 PetscScalar one = 1.0; 3975 Vec tmp; 3976 3977 PetscFunctionBegin; 3978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3979 PetscValidType(mat, 1); 3980 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3981 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3982 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3983 PetscCheckSameComm(mat, 1, b, 2); 3984 PetscCheckSameComm(mat, 1, y, 3); 3985 PetscCheckSameComm(mat, 1, x, 4); 3986 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3987 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); 3988 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); 3989 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); 3990 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); 3991 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); 3992 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3993 MatCheckPreallocated(mat, 1); 3994 3995 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3996 if (mat->factorerrortype) { 3997 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3998 PetscCall(VecSetInf(x)); 3999 } else if (mat->ops->solveadd) { 4000 PetscUseTypeMethod(mat, solveadd, b, y, x); 4001 } else { 4002 /* do the solve then the add manually */ 4003 if (x != y) { 4004 PetscCall(MatSolve(mat, b, x)); 4005 PetscCall(VecAXPY(x, one, y)); 4006 } else { 4007 PetscCall(VecDuplicate(x, &tmp)); 4008 PetscCall(VecCopy(x, tmp)); 4009 PetscCall(MatSolve(mat, b, x)); 4010 PetscCall(VecAXPY(x, one, tmp)); 4011 PetscCall(VecDestroy(&tmp)); 4012 } 4013 } 4014 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4015 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4016 PetscFunctionReturn(PETSC_SUCCESS); 4017 } 4018 4019 /*@ 4020 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4021 4022 Neighbor-wise Collective 4023 4024 Input Parameters: 4025 + mat - the factored matrix 4026 - b - the right-hand-side vector 4027 4028 Output Parameter: 4029 . x - the result vector 4030 4031 Level: developer 4032 4033 Notes: 4034 The vectors `b` and `x` cannot be the same. I.e., one cannot 4035 call `MatSolveTranspose`(A,x,x). 4036 4037 Most users should employ the `KSP` interface for linear solvers 4038 instead of working directly with matrix algebra routines such as this. 4039 See, e.g., `KSPCreate()`. 4040 4041 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4042 @*/ 4043 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4044 { 4045 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4046 4047 PetscFunctionBegin; 4048 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4049 PetscValidType(mat, 1); 4050 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4051 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4052 PetscCheckSameComm(mat, 1, b, 2); 4053 PetscCheckSameComm(mat, 1, x, 3); 4054 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4055 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); 4056 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); 4057 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4058 MatCheckPreallocated(mat, 1); 4059 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4060 if (mat->factorerrortype) { 4061 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4062 PetscCall(VecSetInf(x)); 4063 } else { 4064 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4065 PetscCall((*f)(mat, b, x)); 4066 } 4067 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4068 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4069 PetscFunctionReturn(PETSC_SUCCESS); 4070 } 4071 4072 /*@ 4073 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4074 factored matrix. 4075 4076 Neighbor-wise Collective 4077 4078 Input Parameters: 4079 + mat - the factored matrix 4080 . b - the right-hand-side vector 4081 - y - the vector to be added to 4082 4083 Output Parameter: 4084 . x - the result vector 4085 4086 Level: developer 4087 4088 Note: 4089 The vectors `b` and `x` cannot be the same. I.e., one cannot 4090 call `MatSolveTransposeAdd`(A,x,y,x). 4091 4092 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4093 @*/ 4094 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4095 { 4096 PetscScalar one = 1.0; 4097 Vec tmp; 4098 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4099 4100 PetscFunctionBegin; 4101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4102 PetscValidType(mat, 1); 4103 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4104 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4105 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4106 PetscCheckSameComm(mat, 1, b, 2); 4107 PetscCheckSameComm(mat, 1, y, 3); 4108 PetscCheckSameComm(mat, 1, x, 4); 4109 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4110 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); 4111 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); 4112 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); 4113 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); 4114 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4115 MatCheckPreallocated(mat, 1); 4116 4117 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4118 if (mat->factorerrortype) { 4119 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4120 PetscCall(VecSetInf(x)); 4121 } else if (f) { 4122 PetscCall((*f)(mat, b, y, x)); 4123 } else { 4124 /* do the solve then the add manually */ 4125 if (x != y) { 4126 PetscCall(MatSolveTranspose(mat, b, x)); 4127 PetscCall(VecAXPY(x, one, y)); 4128 } else { 4129 PetscCall(VecDuplicate(x, &tmp)); 4130 PetscCall(VecCopy(x, tmp)); 4131 PetscCall(MatSolveTranspose(mat, b, x)); 4132 PetscCall(VecAXPY(x, one, tmp)); 4133 PetscCall(VecDestroy(&tmp)); 4134 } 4135 } 4136 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4137 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4138 PetscFunctionReturn(PETSC_SUCCESS); 4139 } 4140 4141 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4142 /*@ 4143 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4144 4145 Neighbor-wise Collective 4146 4147 Input Parameters: 4148 + mat - the matrix 4149 . b - the right-hand side 4150 . omega - the relaxation factor 4151 . flag - flag indicating the type of SOR (see below) 4152 . shift - diagonal shift 4153 . its - the number of iterations 4154 - lits - the number of local iterations 4155 4156 Output Parameter: 4157 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4158 4159 SOR Flags: 4160 + `SOR_FORWARD_SWEEP` - forward SOR 4161 . `SOR_BACKWARD_SWEEP` - backward SOR 4162 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4163 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4164 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4165 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4166 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4167 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4168 upper/lower triangular part of matrix to 4169 vector (with omega) 4170 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4171 4172 Level: developer 4173 4174 Notes: 4175 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4176 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4177 on each processor. 4178 4179 Application programmers will not generally use `MatSOR()` directly, 4180 but instead will employ the `KSP`/`PC` interface. 4181 4182 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4183 4184 Most users should employ the `KSP` interface for linear solvers 4185 instead of working directly with matrix algebra routines such as this. 4186 See, e.g., `KSPCreate()`. 4187 4188 Vectors `x` and `b` CANNOT be the same 4189 4190 The flags are implemented as bitwise inclusive or operations. 4191 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4192 to specify a zero initial guess for SSOR. 4193 4194 Developer Note: 4195 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4196 4197 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4198 @*/ 4199 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4200 { 4201 PetscFunctionBegin; 4202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4203 PetscValidType(mat, 1); 4204 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4205 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4206 PetscCheckSameComm(mat, 1, b, 2); 4207 PetscCheckSameComm(mat, 1, x, 8); 4208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4209 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4210 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); 4211 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); 4212 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); 4213 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4214 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4215 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4216 4217 MatCheckPreallocated(mat, 1); 4218 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4219 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4220 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4221 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4222 PetscFunctionReturn(PETSC_SUCCESS); 4223 } 4224 4225 /* 4226 Default matrix copy routine. 4227 */ 4228 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4229 { 4230 PetscInt i, rstart = 0, rend = 0, nz; 4231 const PetscInt *cwork; 4232 const PetscScalar *vwork; 4233 4234 PetscFunctionBegin; 4235 if (B->assembled) PetscCall(MatZeroEntries(B)); 4236 if (str == SAME_NONZERO_PATTERN) { 4237 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4238 for (i = rstart; i < rend; i++) { 4239 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4240 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4241 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4242 } 4243 } else { 4244 PetscCall(MatAYPX(B, 0.0, A, str)); 4245 } 4246 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4247 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4248 PetscFunctionReturn(PETSC_SUCCESS); 4249 } 4250 4251 /*@ 4252 MatCopy - Copies a matrix to another matrix. 4253 4254 Collective 4255 4256 Input Parameters: 4257 + A - the matrix 4258 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4259 4260 Output Parameter: 4261 . B - where the copy is put 4262 4263 Level: intermediate 4264 4265 Notes: 4266 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4267 4268 `MatCopy()` copies the matrix entries of a matrix to another existing 4269 matrix (after first zeroing the second matrix). A related routine is 4270 `MatConvert()`, which first creates a new matrix and then copies the data. 4271 4272 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4273 @*/ 4274 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4275 { 4276 PetscInt i; 4277 4278 PetscFunctionBegin; 4279 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4280 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4281 PetscValidType(A, 1); 4282 PetscValidType(B, 2); 4283 PetscCheckSameComm(A, 1, B, 2); 4284 MatCheckPreallocated(B, 2); 4285 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4286 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4287 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, 4288 A->cmap->N, B->cmap->N); 4289 MatCheckPreallocated(A, 1); 4290 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4291 4292 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4293 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4294 else PetscCall(MatCopy_Basic(A, B, str)); 4295 4296 B->stencil.dim = A->stencil.dim; 4297 B->stencil.noc = A->stencil.noc; 4298 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4299 B->stencil.dims[i] = A->stencil.dims[i]; 4300 B->stencil.starts[i] = A->stencil.starts[i]; 4301 } 4302 4303 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4304 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4305 PetscFunctionReturn(PETSC_SUCCESS); 4306 } 4307 4308 /*@ 4309 MatConvert - Converts a matrix to another matrix, either of the same 4310 or different type. 4311 4312 Collective 4313 4314 Input Parameters: 4315 + mat - the matrix 4316 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4317 same type as the original matrix. 4318 - reuse - denotes if the destination matrix is to be created or reused. 4319 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 4320 `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). 4321 4322 Output Parameter: 4323 . M - pointer to place new matrix 4324 4325 Level: intermediate 4326 4327 Notes: 4328 `MatConvert()` first creates a new matrix and then copies the data from 4329 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4330 entries of one matrix to another already existing matrix context. 4331 4332 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4333 the MPI communicator of the generated matrix is always the same as the communicator 4334 of the input matrix. 4335 4336 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4337 @*/ 4338 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4339 { 4340 PetscBool sametype, issame, flg; 4341 PetscBool3 issymmetric, ishermitian; 4342 char convname[256], mtype[256]; 4343 Mat B; 4344 4345 PetscFunctionBegin; 4346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4347 PetscValidType(mat, 1); 4348 PetscAssertPointer(M, 4); 4349 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4350 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4351 MatCheckPreallocated(mat, 1); 4352 4353 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4354 if (flg) newtype = mtype; 4355 4356 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4357 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4358 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4359 if (reuse == MAT_REUSE_MATRIX) { 4360 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4361 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4362 } 4363 4364 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4365 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4366 PetscFunctionReturn(PETSC_SUCCESS); 4367 } 4368 4369 /* Cache Mat options because some converters use MatHeaderReplace */ 4370 issymmetric = mat->symmetric; 4371 ishermitian = mat->hermitian; 4372 4373 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4374 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4375 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4376 } else { 4377 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4378 const char *prefix[3] = {"seq", "mpi", ""}; 4379 PetscInt i; 4380 /* 4381 Order of precedence: 4382 0) See if newtype is a superclass of the current matrix. 4383 1) See if a specialized converter is known to the current matrix. 4384 2) See if a specialized converter is known to the desired matrix class. 4385 3) See if a good general converter is registered for the desired class 4386 (as of 6/27/03 only MATMPIADJ falls into this category). 4387 4) See if a good general converter is known for the current matrix. 4388 5) Use a really basic converter. 4389 */ 4390 4391 /* 0) See if newtype is a superclass of the current matrix. 4392 i.e mat is mpiaij and newtype is aij */ 4393 for (i = 0; i < 2; i++) { 4394 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4395 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4396 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4397 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4398 if (flg) { 4399 if (reuse == MAT_INPLACE_MATRIX) { 4400 PetscCall(PetscInfo(mat, "Early return\n")); 4401 PetscFunctionReturn(PETSC_SUCCESS); 4402 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4403 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4404 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4405 PetscFunctionReturn(PETSC_SUCCESS); 4406 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4407 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4408 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4409 PetscFunctionReturn(PETSC_SUCCESS); 4410 } 4411 } 4412 } 4413 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4414 for (i = 0; i < 3; i++) { 4415 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4416 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4417 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4418 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4419 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4420 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4421 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4422 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4423 if (conv) goto foundconv; 4424 } 4425 4426 /* 2) See if a specialized converter is known to the desired matrix class. */ 4427 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4428 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4429 PetscCall(MatSetType(B, newtype)); 4430 for (i = 0; i < 3; i++) { 4431 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4432 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4433 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4434 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4435 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4436 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4437 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4438 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4439 if (conv) { 4440 PetscCall(MatDestroy(&B)); 4441 goto foundconv; 4442 } 4443 } 4444 4445 /* 3) See if a good general converter is registered for the desired class */ 4446 conv = B->ops->convertfrom; 4447 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4448 PetscCall(MatDestroy(&B)); 4449 if (conv) goto foundconv; 4450 4451 /* 4) See if a good general converter is known for the current matrix */ 4452 if (mat->ops->convert) conv = mat->ops->convert; 4453 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4454 if (conv) goto foundconv; 4455 4456 /* 5) Use a really basic converter. */ 4457 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4458 conv = MatConvert_Basic; 4459 4460 foundconv: 4461 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4462 PetscCall((*conv)(mat, newtype, reuse, M)); 4463 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4464 /* the block sizes must be same if the mappings are copied over */ 4465 (*M)->rmap->bs = mat->rmap->bs; 4466 (*M)->cmap->bs = mat->cmap->bs; 4467 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4468 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4469 (*M)->rmap->mapping = mat->rmap->mapping; 4470 (*M)->cmap->mapping = mat->cmap->mapping; 4471 } 4472 (*M)->stencil.dim = mat->stencil.dim; 4473 (*M)->stencil.noc = mat->stencil.noc; 4474 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4475 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4476 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4477 } 4478 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4479 } 4480 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4481 4482 /* Copy Mat options */ 4483 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4484 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4485 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4486 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4487 PetscFunctionReturn(PETSC_SUCCESS); 4488 } 4489 4490 /*@C 4491 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4492 4493 Not Collective 4494 4495 Input Parameter: 4496 . mat - the matrix, must be a factored matrix 4497 4498 Output Parameter: 4499 . type - the string name of the package (do not free this string) 4500 4501 Level: intermediate 4502 4503 Fortran Note: 4504 Pass in an empty string that is long enough and the package name will be copied into it. 4505 4506 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4507 @*/ 4508 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4509 { 4510 PetscErrorCode (*conv)(Mat, MatSolverType *); 4511 4512 PetscFunctionBegin; 4513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4514 PetscValidType(mat, 1); 4515 PetscAssertPointer(type, 2); 4516 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4517 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4518 if (conv) PetscCall((*conv)(mat, type)); 4519 else *type = MATSOLVERPETSC; 4520 PetscFunctionReturn(PETSC_SUCCESS); 4521 } 4522 4523 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4524 struct _MatSolverTypeForSpecifcType { 4525 MatType mtype; 4526 /* no entry for MAT_FACTOR_NONE */ 4527 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4528 MatSolverTypeForSpecifcType next; 4529 }; 4530 4531 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4532 struct _MatSolverTypeHolder { 4533 char *name; 4534 MatSolverTypeForSpecifcType handlers; 4535 MatSolverTypeHolder next; 4536 }; 4537 4538 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4539 4540 /*@C 4541 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4542 4543 Logically Collective, No Fortran Support 4544 4545 Input Parameters: 4546 + package - name of the package, for example petsc or superlu 4547 . mtype - the matrix type that works with this package 4548 . ftype - the type of factorization supported by the package 4549 - createfactor - routine that will create the factored matrix ready to be used 4550 4551 Level: developer 4552 4553 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4554 `MatGetFactor()` 4555 @*/ 4556 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4557 { 4558 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4559 PetscBool flg; 4560 MatSolverTypeForSpecifcType inext, iprev = NULL; 4561 4562 PetscFunctionBegin; 4563 PetscCall(MatInitializePackage()); 4564 if (!next) { 4565 PetscCall(PetscNew(&MatSolverTypeHolders)); 4566 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4567 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4568 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4569 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4570 PetscFunctionReturn(PETSC_SUCCESS); 4571 } 4572 while (next) { 4573 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4574 if (flg) { 4575 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4576 inext = next->handlers; 4577 while (inext) { 4578 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4579 if (flg) { 4580 inext->createfactor[(int)ftype - 1] = createfactor; 4581 PetscFunctionReturn(PETSC_SUCCESS); 4582 } 4583 iprev = inext; 4584 inext = inext->next; 4585 } 4586 PetscCall(PetscNew(&iprev->next)); 4587 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4588 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4589 PetscFunctionReturn(PETSC_SUCCESS); 4590 } 4591 prev = next; 4592 next = next->next; 4593 } 4594 PetscCall(PetscNew(&prev->next)); 4595 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4596 PetscCall(PetscNew(&prev->next->handlers)); 4597 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4598 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4599 PetscFunctionReturn(PETSC_SUCCESS); 4600 } 4601 4602 /*@C 4603 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4604 4605 Input Parameters: 4606 + type - name of the package, for example petsc or superlu, if this is 'NULL', then the first result that satisfies the other criteria is returned 4607 . ftype - the type of factorization supported by the type 4608 - mtype - the matrix type that works with this type 4609 4610 Output Parameters: 4611 + foundtype - `PETSC_TRUE` if the type was registered 4612 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4613 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4614 4615 Calling sequence of `createfactor`: 4616 + A - the matrix providing the factor matrix 4617 . mtype - the `MatType` of the factor requested 4618 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4619 4620 Level: developer 4621 4622 Note: 4623 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4624 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4625 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4626 4627 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4628 `MatInitializePackage()` 4629 @*/ 4630 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B)) 4631 { 4632 MatSolverTypeHolder next = MatSolverTypeHolders; 4633 PetscBool flg; 4634 MatSolverTypeForSpecifcType inext; 4635 4636 PetscFunctionBegin; 4637 if (foundtype) *foundtype = PETSC_FALSE; 4638 if (foundmtype) *foundmtype = PETSC_FALSE; 4639 if (createfactor) *createfactor = NULL; 4640 4641 if (type) { 4642 while (next) { 4643 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4644 if (flg) { 4645 if (foundtype) *foundtype = PETSC_TRUE; 4646 inext = next->handlers; 4647 while (inext) { 4648 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4649 if (flg) { 4650 if (foundmtype) *foundmtype = PETSC_TRUE; 4651 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4652 PetscFunctionReturn(PETSC_SUCCESS); 4653 } 4654 inext = inext->next; 4655 } 4656 } 4657 next = next->next; 4658 } 4659 } else { 4660 while (next) { 4661 inext = next->handlers; 4662 while (inext) { 4663 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4664 if (flg && inext->createfactor[(int)ftype - 1]) { 4665 if (foundtype) *foundtype = PETSC_TRUE; 4666 if (foundmtype) *foundmtype = PETSC_TRUE; 4667 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4668 PetscFunctionReturn(PETSC_SUCCESS); 4669 } 4670 inext = inext->next; 4671 } 4672 next = next->next; 4673 } 4674 /* try with base classes inext->mtype */ 4675 next = MatSolverTypeHolders; 4676 while (next) { 4677 inext = next->handlers; 4678 while (inext) { 4679 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4680 if (flg && inext->createfactor[(int)ftype - 1]) { 4681 if (foundtype) *foundtype = PETSC_TRUE; 4682 if (foundmtype) *foundmtype = PETSC_TRUE; 4683 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4684 PetscFunctionReturn(PETSC_SUCCESS); 4685 } 4686 inext = inext->next; 4687 } 4688 next = next->next; 4689 } 4690 } 4691 PetscFunctionReturn(PETSC_SUCCESS); 4692 } 4693 4694 PetscErrorCode MatSolverTypeDestroy(void) 4695 { 4696 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4697 MatSolverTypeForSpecifcType inext, iprev; 4698 4699 PetscFunctionBegin; 4700 while (next) { 4701 PetscCall(PetscFree(next->name)); 4702 inext = next->handlers; 4703 while (inext) { 4704 PetscCall(PetscFree(inext->mtype)); 4705 iprev = inext; 4706 inext = inext->next; 4707 PetscCall(PetscFree(iprev)); 4708 } 4709 prev = next; 4710 next = next->next; 4711 PetscCall(PetscFree(prev)); 4712 } 4713 MatSolverTypeHolders = NULL; 4714 PetscFunctionReturn(PETSC_SUCCESS); 4715 } 4716 4717 /*@ 4718 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4719 4720 Logically Collective 4721 4722 Input Parameter: 4723 . mat - the matrix 4724 4725 Output Parameter: 4726 . flg - `PETSC_TRUE` if uses the ordering 4727 4728 Level: developer 4729 4730 Note: 4731 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4732 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4733 4734 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4735 @*/ 4736 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4737 { 4738 PetscFunctionBegin; 4739 *flg = mat->canuseordering; 4740 PetscFunctionReturn(PETSC_SUCCESS); 4741 } 4742 4743 /*@ 4744 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4745 4746 Logically Collective 4747 4748 Input Parameters: 4749 + mat - the matrix obtained with `MatGetFactor()` 4750 - ftype - the factorization type to be used 4751 4752 Output Parameter: 4753 . otype - the preferred ordering type 4754 4755 Level: developer 4756 4757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4758 @*/ 4759 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4760 { 4761 PetscFunctionBegin; 4762 *otype = mat->preferredordering[ftype]; 4763 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4764 PetscFunctionReturn(PETSC_SUCCESS); 4765 } 4766 4767 /*@ 4768 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4769 4770 Collective 4771 4772 Input Parameters: 4773 + mat - the matrix 4774 . type - name of solver type, for example, superlu, petsc (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies 4775 the other criteria is returned 4776 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4777 4778 Output Parameter: 4779 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4780 4781 Options Database Keys: 4782 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4783 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4784 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4785 4786 Level: intermediate 4787 4788 Notes: 4789 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4790 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4791 4792 Users usually access the factorization solvers via `KSP` 4793 4794 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4795 such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir 4796 4797 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4798 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4799 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4800 4801 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4802 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4803 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4804 4805 Developer Note: 4806 This should actually be called `MatCreateFactor()` since it creates a new factor object 4807 4808 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4809 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4810 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4811 @*/ 4812 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4813 { 4814 PetscBool foundtype, foundmtype; 4815 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4816 4817 PetscFunctionBegin; 4818 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4819 PetscValidType(mat, 1); 4820 4821 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4822 MatCheckPreallocated(mat, 1); 4823 4824 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4825 if (!foundtype) { 4826 if (type) { 4827 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], 4828 ((PetscObject)mat)->type_name, type); 4829 } else { 4830 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); 4831 } 4832 } 4833 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4834 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); 4835 4836 PetscCall((*conv)(mat, ftype, f)); 4837 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4838 PetscFunctionReturn(PETSC_SUCCESS); 4839 } 4840 4841 /*@ 4842 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4843 4844 Not Collective 4845 4846 Input Parameters: 4847 + mat - the matrix 4848 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4849 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4850 4851 Output Parameter: 4852 . flg - PETSC_TRUE if the factorization is available 4853 4854 Level: intermediate 4855 4856 Notes: 4857 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4858 such as pastix, superlu, mumps etc. 4859 4860 PETSc must have been ./configure to use the external solver, using the option --download-package 4861 4862 Developer Note: 4863 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4864 4865 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4866 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4867 @*/ 4868 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4869 { 4870 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4871 4872 PetscFunctionBegin; 4873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4874 PetscAssertPointer(flg, 4); 4875 4876 *flg = PETSC_FALSE; 4877 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4878 4879 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4880 MatCheckPreallocated(mat, 1); 4881 4882 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4883 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4884 PetscFunctionReturn(PETSC_SUCCESS); 4885 } 4886 4887 /*@ 4888 MatDuplicate - Duplicates a matrix including the non-zero structure. 4889 4890 Collective 4891 4892 Input Parameters: 4893 + mat - the matrix 4894 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4895 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4896 4897 Output Parameter: 4898 . M - pointer to place new matrix 4899 4900 Level: intermediate 4901 4902 Notes: 4903 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4904 4905 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4906 4907 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. 4908 4909 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4910 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4911 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4912 4913 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4914 @*/ 4915 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4916 { 4917 Mat B; 4918 VecType vtype; 4919 PetscInt i; 4920 PetscObject dm, container_h, container_d; 4921 void (*viewf)(void); 4922 4923 PetscFunctionBegin; 4924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4925 PetscValidType(mat, 1); 4926 PetscAssertPointer(M, 3); 4927 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4928 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4929 MatCheckPreallocated(mat, 1); 4930 4931 *M = NULL; 4932 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4933 PetscUseTypeMethod(mat, duplicate, op, M); 4934 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4935 B = *M; 4936 4937 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4938 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4939 PetscCall(MatGetVecType(mat, &vtype)); 4940 PetscCall(MatSetVecType(B, vtype)); 4941 4942 B->stencil.dim = mat->stencil.dim; 4943 B->stencil.noc = mat->stencil.noc; 4944 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4945 B->stencil.dims[i] = mat->stencil.dims[i]; 4946 B->stencil.starts[i] = mat->stencil.starts[i]; 4947 } 4948 4949 B->nooffproczerorows = mat->nooffproczerorows; 4950 B->nooffprocentries = mat->nooffprocentries; 4951 4952 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4953 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4954 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4955 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4956 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4957 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4958 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4959 PetscFunctionReturn(PETSC_SUCCESS); 4960 } 4961 4962 /*@ 4963 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4964 4965 Logically Collective 4966 4967 Input Parameter: 4968 . mat - the matrix 4969 4970 Output Parameter: 4971 . v - the diagonal of the matrix 4972 4973 Level: intermediate 4974 4975 Note: 4976 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4977 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4978 is larger than `ndiag`, the values of the remaining entries are unspecified. 4979 4980 Currently only correct in parallel for square matrices. 4981 4982 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4983 @*/ 4984 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4985 { 4986 PetscFunctionBegin; 4987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4988 PetscValidType(mat, 1); 4989 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4990 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4991 MatCheckPreallocated(mat, 1); 4992 if (PetscDefined(USE_DEBUG)) { 4993 PetscInt nv, row, col, ndiag; 4994 4995 PetscCall(VecGetLocalSize(v, &nv)); 4996 PetscCall(MatGetLocalSize(mat, &row, &col)); 4997 ndiag = PetscMin(row, col); 4998 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); 4999 } 5000 5001 PetscUseTypeMethod(mat, getdiagonal, v); 5002 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5003 PetscFunctionReturn(PETSC_SUCCESS); 5004 } 5005 5006 /*@ 5007 MatGetRowMin - Gets the minimum value (of the real part) of each 5008 row of the matrix 5009 5010 Logically Collective 5011 5012 Input Parameter: 5013 . mat - the matrix 5014 5015 Output Parameters: 5016 + v - the vector for storing the maximums 5017 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5018 5019 Level: intermediate 5020 5021 Note: 5022 The result of this call are the same as if one converted the matrix to dense format 5023 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5024 5025 This code is only implemented for a couple of matrix formats. 5026 5027 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5028 `MatGetRowMax()` 5029 @*/ 5030 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5031 { 5032 PetscFunctionBegin; 5033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5034 PetscValidType(mat, 1); 5035 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5036 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5037 5038 if (!mat->cmap->N) { 5039 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5040 if (idx) { 5041 PetscInt i, m = mat->rmap->n; 5042 for (i = 0; i < m; i++) idx[i] = -1; 5043 } 5044 } else { 5045 MatCheckPreallocated(mat, 1); 5046 } 5047 PetscUseTypeMethod(mat, getrowmin, v, idx); 5048 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5049 PetscFunctionReturn(PETSC_SUCCESS); 5050 } 5051 5052 /*@ 5053 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5054 row of the matrix 5055 5056 Logically Collective 5057 5058 Input Parameter: 5059 . mat - the matrix 5060 5061 Output Parameters: 5062 + v - the vector for storing the minimums 5063 - idx - the indices of the column found for each row (or `NULL` if not needed) 5064 5065 Level: intermediate 5066 5067 Notes: 5068 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5069 row is 0 (the first column). 5070 5071 This code is only implemented for a couple of matrix formats. 5072 5073 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5074 @*/ 5075 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5076 { 5077 PetscFunctionBegin; 5078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5079 PetscValidType(mat, 1); 5080 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5081 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5082 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5083 5084 if (!mat->cmap->N) { 5085 PetscCall(VecSet(v, 0.0)); 5086 if (idx) { 5087 PetscInt i, m = mat->rmap->n; 5088 for (i = 0; i < m; i++) idx[i] = -1; 5089 } 5090 } else { 5091 MatCheckPreallocated(mat, 1); 5092 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5093 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5094 } 5095 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5096 PetscFunctionReturn(PETSC_SUCCESS); 5097 } 5098 5099 /*@ 5100 MatGetRowMax - Gets the maximum value (of the real part) of each 5101 row of the matrix 5102 5103 Logically Collective 5104 5105 Input Parameter: 5106 . mat - the matrix 5107 5108 Output Parameters: 5109 + v - the vector for storing the maximums 5110 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5111 5112 Level: intermediate 5113 5114 Notes: 5115 The result of this call are the same as if one converted the matrix to dense format 5116 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5117 5118 This code is only implemented for a couple of matrix formats. 5119 5120 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5121 @*/ 5122 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5123 { 5124 PetscFunctionBegin; 5125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5126 PetscValidType(mat, 1); 5127 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5128 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5129 5130 if (!mat->cmap->N) { 5131 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5132 if (idx) { 5133 PetscInt i, m = mat->rmap->n; 5134 for (i = 0; i < m; i++) idx[i] = -1; 5135 } 5136 } else { 5137 MatCheckPreallocated(mat, 1); 5138 PetscUseTypeMethod(mat, getrowmax, v, idx); 5139 } 5140 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5141 PetscFunctionReturn(PETSC_SUCCESS); 5142 } 5143 5144 /*@ 5145 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5146 row of the matrix 5147 5148 Logically Collective 5149 5150 Input Parameter: 5151 . mat - the matrix 5152 5153 Output Parameters: 5154 + v - the vector for storing the maximums 5155 - idx - the indices of the column found for each row (or `NULL` if not needed) 5156 5157 Level: intermediate 5158 5159 Notes: 5160 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5161 row is 0 (the first column). 5162 5163 This code is only implemented for a couple of matrix formats. 5164 5165 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5166 @*/ 5167 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5168 { 5169 PetscFunctionBegin; 5170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5171 PetscValidType(mat, 1); 5172 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5173 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5174 5175 if (!mat->cmap->N) { 5176 PetscCall(VecSet(v, 0.0)); 5177 if (idx) { 5178 PetscInt i, m = mat->rmap->n; 5179 for (i = 0; i < m; i++) idx[i] = -1; 5180 } 5181 } else { 5182 MatCheckPreallocated(mat, 1); 5183 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5184 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5185 } 5186 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5187 PetscFunctionReturn(PETSC_SUCCESS); 5188 } 5189 5190 /*@ 5191 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5192 5193 Logically Collective 5194 5195 Input Parameter: 5196 . mat - the matrix 5197 5198 Output Parameter: 5199 . v - the vector for storing the sum 5200 5201 Level: intermediate 5202 5203 This code is only implemented for a couple of matrix formats. 5204 5205 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5206 @*/ 5207 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5208 { 5209 PetscFunctionBegin; 5210 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5211 PetscValidType(mat, 1); 5212 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5213 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5214 5215 if (!mat->cmap->N) { 5216 PetscCall(VecSet(v, 0.0)); 5217 } else { 5218 MatCheckPreallocated(mat, 1); 5219 PetscUseTypeMethod(mat, getrowsumabs, v); 5220 } 5221 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5222 PetscFunctionReturn(PETSC_SUCCESS); 5223 } 5224 5225 /*@ 5226 MatGetRowSum - Gets the sum of each row of the matrix 5227 5228 Logically or Neighborhood Collective 5229 5230 Input Parameter: 5231 . mat - the matrix 5232 5233 Output Parameter: 5234 . v - the vector for storing the sum of rows 5235 5236 Level: intermediate 5237 5238 Note: 5239 This code is slow since it is not currently specialized for different formats 5240 5241 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5242 @*/ 5243 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5244 { 5245 Vec ones; 5246 5247 PetscFunctionBegin; 5248 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5249 PetscValidType(mat, 1); 5250 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5251 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5252 MatCheckPreallocated(mat, 1); 5253 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5254 PetscCall(VecSet(ones, 1.)); 5255 PetscCall(MatMult(mat, ones, v)); 5256 PetscCall(VecDestroy(&ones)); 5257 PetscFunctionReturn(PETSC_SUCCESS); 5258 } 5259 5260 /*@ 5261 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5262 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5263 5264 Collective 5265 5266 Input Parameter: 5267 . mat - the matrix to provide the transpose 5268 5269 Output Parameter: 5270 . 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 5271 5272 Level: advanced 5273 5274 Note: 5275 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 5276 routine allows bypassing that call. 5277 5278 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5279 @*/ 5280 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5281 { 5282 PetscContainer rB = NULL; 5283 MatParentState *rb = NULL; 5284 5285 PetscFunctionBegin; 5286 PetscCall(PetscNew(&rb)); 5287 rb->id = ((PetscObject)mat)->id; 5288 rb->state = 0; 5289 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5290 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5291 PetscCall(PetscContainerSetPointer(rB, rb)); 5292 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5293 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5294 PetscCall(PetscObjectDereference((PetscObject)rB)); 5295 PetscFunctionReturn(PETSC_SUCCESS); 5296 } 5297 5298 /*@ 5299 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5300 5301 Collective 5302 5303 Input Parameters: 5304 + mat - the matrix to transpose 5305 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5306 5307 Output Parameter: 5308 . B - the transpose 5309 5310 Level: intermediate 5311 5312 Notes: 5313 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5314 5315 `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 5316 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5317 5318 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. 5319 5320 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5321 5322 If mat is unchanged from the last call this function returns immediately without recomputing the result 5323 5324 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5325 5326 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5327 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5328 @*/ 5329 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5330 { 5331 PetscContainer rB = NULL; 5332 MatParentState *rb = NULL; 5333 5334 PetscFunctionBegin; 5335 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5336 PetscValidType(mat, 1); 5337 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5338 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5339 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5340 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5341 MatCheckPreallocated(mat, 1); 5342 if (reuse == MAT_REUSE_MATRIX) { 5343 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5344 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5345 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5346 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5347 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5348 } 5349 5350 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5351 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5352 PetscUseTypeMethod(mat, transpose, reuse, B); 5353 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5354 } 5355 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5356 5357 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5358 if (reuse != MAT_INPLACE_MATRIX) { 5359 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5360 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5361 rb->state = ((PetscObject)mat)->state; 5362 rb->nonzerostate = mat->nonzerostate; 5363 } 5364 PetscFunctionReturn(PETSC_SUCCESS); 5365 } 5366 5367 /*@ 5368 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5369 5370 Collective 5371 5372 Input Parameter: 5373 . A - the matrix to transpose 5374 5375 Output Parameter: 5376 . 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 5377 numerical portion. 5378 5379 Level: intermediate 5380 5381 Note: 5382 This is not supported for many matrix types, use `MatTranspose()` in those cases 5383 5384 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5385 @*/ 5386 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5387 { 5388 PetscFunctionBegin; 5389 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5390 PetscValidType(A, 1); 5391 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5392 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5393 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5394 PetscUseTypeMethod(A, transposesymbolic, B); 5395 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5396 5397 PetscCall(MatTransposeSetPrecursor(A, *B)); 5398 PetscFunctionReturn(PETSC_SUCCESS); 5399 } 5400 5401 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5402 { 5403 PetscContainer rB; 5404 MatParentState *rb; 5405 5406 PetscFunctionBegin; 5407 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5408 PetscValidType(A, 1); 5409 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5410 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5411 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5412 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5413 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5414 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5415 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5416 PetscFunctionReturn(PETSC_SUCCESS); 5417 } 5418 5419 /*@ 5420 MatIsTranspose - Test whether a matrix is another one's transpose, 5421 or its own, in which case it tests symmetry. 5422 5423 Collective 5424 5425 Input Parameters: 5426 + A - the matrix to test 5427 . B - the matrix to test against, this can equal the first parameter 5428 - tol - tolerance, differences between entries smaller than this are counted as zero 5429 5430 Output Parameter: 5431 . flg - the result 5432 5433 Level: intermediate 5434 5435 Notes: 5436 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5437 test involves parallel copies of the block off-diagonal parts of the matrix. 5438 5439 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5440 @*/ 5441 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5442 { 5443 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5444 5445 PetscFunctionBegin; 5446 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5447 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5448 PetscAssertPointer(flg, 4); 5449 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5450 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5451 *flg = PETSC_FALSE; 5452 if (f && g) { 5453 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5454 PetscCall((*f)(A, B, tol, flg)); 5455 } else { 5456 MatType mattype; 5457 5458 PetscCall(MatGetType(f ? B : A, &mattype)); 5459 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5460 } 5461 PetscFunctionReturn(PETSC_SUCCESS); 5462 } 5463 5464 /*@ 5465 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5466 5467 Collective 5468 5469 Input Parameters: 5470 + mat - the matrix to transpose and complex conjugate 5471 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5472 5473 Output Parameter: 5474 . B - the Hermitian transpose 5475 5476 Level: intermediate 5477 5478 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5479 @*/ 5480 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5481 { 5482 PetscFunctionBegin; 5483 PetscCall(MatTranspose(mat, reuse, B)); 5484 #if defined(PETSC_USE_COMPLEX) 5485 PetscCall(MatConjugate(*B)); 5486 #endif 5487 PetscFunctionReturn(PETSC_SUCCESS); 5488 } 5489 5490 /*@ 5491 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5492 5493 Collective 5494 5495 Input Parameters: 5496 + A - the matrix to test 5497 . B - the matrix to test against, this can equal the first parameter 5498 - tol - tolerance, differences between entries smaller than this are counted as zero 5499 5500 Output Parameter: 5501 . flg - the result 5502 5503 Level: intermediate 5504 5505 Notes: 5506 Only available for `MATAIJ` matrices. 5507 5508 The sequential algorithm 5509 has a running time of the order of the number of nonzeros; the parallel 5510 test involves parallel copies of the block off-diagonal parts of the matrix. 5511 5512 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5513 @*/ 5514 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5515 { 5516 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5517 5518 PetscFunctionBegin; 5519 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5520 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5521 PetscAssertPointer(flg, 4); 5522 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5523 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5524 if (f && g) { 5525 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5526 PetscCall((*f)(A, B, tol, flg)); 5527 } 5528 PetscFunctionReturn(PETSC_SUCCESS); 5529 } 5530 5531 /*@ 5532 MatPermute - Creates a new matrix with rows and columns permuted from the 5533 original. 5534 5535 Collective 5536 5537 Input Parameters: 5538 + mat - the matrix to permute 5539 . row - row permutation, each processor supplies only the permutation for its rows 5540 - col - column permutation, each processor supplies only the permutation for its columns 5541 5542 Output Parameter: 5543 . B - the permuted matrix 5544 5545 Level: advanced 5546 5547 Note: 5548 The index sets map from row/col of permuted matrix to row/col of original matrix. 5549 The index sets should be on the same communicator as mat and have the same local sizes. 5550 5551 Developer Note: 5552 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5553 exploit the fact that row and col are permutations, consider implementing the 5554 more general `MatCreateSubMatrix()` instead. 5555 5556 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5557 @*/ 5558 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5559 { 5560 PetscFunctionBegin; 5561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5562 PetscValidType(mat, 1); 5563 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5564 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5565 PetscAssertPointer(B, 4); 5566 PetscCheckSameComm(mat, 1, row, 2); 5567 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5568 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5569 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5570 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5571 MatCheckPreallocated(mat, 1); 5572 5573 if (mat->ops->permute) { 5574 PetscUseTypeMethod(mat, permute, row, col, B); 5575 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5576 } else { 5577 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5578 } 5579 PetscFunctionReturn(PETSC_SUCCESS); 5580 } 5581 5582 /*@ 5583 MatEqual - Compares two matrices. 5584 5585 Collective 5586 5587 Input Parameters: 5588 + A - the first matrix 5589 - B - the second matrix 5590 5591 Output Parameter: 5592 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5593 5594 Level: intermediate 5595 5596 .seealso: [](ch_matrices), `Mat` 5597 @*/ 5598 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5599 { 5600 PetscFunctionBegin; 5601 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5602 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5603 PetscValidType(A, 1); 5604 PetscValidType(B, 2); 5605 PetscAssertPointer(flg, 3); 5606 PetscCheckSameComm(A, 1, B, 2); 5607 MatCheckPreallocated(A, 1); 5608 MatCheckPreallocated(B, 2); 5609 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5610 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5611 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, 5612 B->cmap->N); 5613 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5614 PetscUseTypeMethod(A, equal, B, flg); 5615 } else { 5616 PetscCall(MatMultEqual(A, B, 10, flg)); 5617 } 5618 PetscFunctionReturn(PETSC_SUCCESS); 5619 } 5620 5621 /*@ 5622 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5623 matrices that are stored as vectors. Either of the two scaling 5624 matrices can be `NULL`. 5625 5626 Collective 5627 5628 Input Parameters: 5629 + mat - the matrix to be scaled 5630 . l - the left scaling vector (or `NULL`) 5631 - r - the right scaling vector (or `NULL`) 5632 5633 Level: intermediate 5634 5635 Note: 5636 `MatDiagonalScale()` computes $A = LAR$, where 5637 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5638 The L scales the rows of the matrix, the R scales the columns of the matrix. 5639 5640 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5641 @*/ 5642 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5643 { 5644 PetscFunctionBegin; 5645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5646 PetscValidType(mat, 1); 5647 if (l) { 5648 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5649 PetscCheckSameComm(mat, 1, l, 2); 5650 } 5651 if (r) { 5652 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5653 PetscCheckSameComm(mat, 1, r, 3); 5654 } 5655 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5656 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5657 MatCheckPreallocated(mat, 1); 5658 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5659 5660 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5661 PetscUseTypeMethod(mat, diagonalscale, l, r); 5662 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5663 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5664 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5665 PetscFunctionReturn(PETSC_SUCCESS); 5666 } 5667 5668 /*@ 5669 MatScale - Scales all elements of a matrix by a given number. 5670 5671 Logically Collective 5672 5673 Input Parameters: 5674 + mat - the matrix to be scaled 5675 - a - the scaling value 5676 5677 Level: intermediate 5678 5679 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5680 @*/ 5681 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5682 { 5683 PetscFunctionBegin; 5684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5685 PetscValidType(mat, 1); 5686 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5687 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5688 PetscValidLogicalCollectiveScalar(mat, a, 2); 5689 MatCheckPreallocated(mat, 1); 5690 5691 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5692 if (a != (PetscScalar)1.0) { 5693 PetscUseTypeMethod(mat, scale, a); 5694 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5695 } 5696 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5697 PetscFunctionReturn(PETSC_SUCCESS); 5698 } 5699 5700 /*@ 5701 MatNorm - Calculates various norms of a matrix. 5702 5703 Collective 5704 5705 Input Parameters: 5706 + mat - the matrix 5707 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5708 5709 Output Parameter: 5710 . nrm - the resulting norm 5711 5712 Level: intermediate 5713 5714 .seealso: [](ch_matrices), `Mat` 5715 @*/ 5716 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5717 { 5718 PetscFunctionBegin; 5719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5720 PetscValidType(mat, 1); 5721 PetscAssertPointer(nrm, 3); 5722 5723 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5724 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5725 MatCheckPreallocated(mat, 1); 5726 5727 PetscUseTypeMethod(mat, norm, type, nrm); 5728 PetscFunctionReturn(PETSC_SUCCESS); 5729 } 5730 5731 /* 5732 This variable is used to prevent counting of MatAssemblyBegin() that 5733 are called from within a MatAssemblyEnd(). 5734 */ 5735 static PetscInt MatAssemblyEnd_InUse = 0; 5736 /*@ 5737 MatAssemblyBegin - Begins assembling the matrix. This routine should 5738 be called after completing all calls to `MatSetValues()`. 5739 5740 Collective 5741 5742 Input Parameters: 5743 + mat - the matrix 5744 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5745 5746 Level: beginner 5747 5748 Notes: 5749 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5750 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5751 5752 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5753 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5754 using the matrix. 5755 5756 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5757 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 5758 a global collective operation requiring all processes that share the matrix. 5759 5760 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5761 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5762 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5763 5764 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5765 @*/ 5766 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5767 { 5768 PetscFunctionBegin; 5769 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5770 PetscValidType(mat, 1); 5771 MatCheckPreallocated(mat, 1); 5772 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5773 if (mat->assembled) { 5774 mat->was_assembled = PETSC_TRUE; 5775 mat->assembled = PETSC_FALSE; 5776 } 5777 5778 if (!MatAssemblyEnd_InUse) { 5779 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5780 PetscTryTypeMethod(mat, assemblybegin, type); 5781 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5782 } else PetscTryTypeMethod(mat, assemblybegin, type); 5783 PetscFunctionReturn(PETSC_SUCCESS); 5784 } 5785 5786 /*@ 5787 MatAssembled - Indicates if a matrix has been assembled and is ready for 5788 use; for example, in matrix-vector product. 5789 5790 Not Collective 5791 5792 Input Parameter: 5793 . mat - the matrix 5794 5795 Output Parameter: 5796 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5797 5798 Level: advanced 5799 5800 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5801 @*/ 5802 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5803 { 5804 PetscFunctionBegin; 5805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5806 PetscAssertPointer(assembled, 2); 5807 *assembled = mat->assembled; 5808 PetscFunctionReturn(PETSC_SUCCESS); 5809 } 5810 5811 /*@ 5812 MatAssemblyEnd - Completes assembling the matrix. This routine should 5813 be called after `MatAssemblyBegin()`. 5814 5815 Collective 5816 5817 Input Parameters: 5818 + mat - the matrix 5819 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5820 5821 Options Database Keys: 5822 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5823 . -mat_view ::ascii_info_detail - Prints more detailed info 5824 . -mat_view - Prints matrix in ASCII format 5825 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5826 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5827 . -display <name> - Sets display name (default is host) 5828 . -draw_pause <sec> - Sets number of seconds to pause after display 5829 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5830 . -viewer_socket_machine <machine> - Machine to use for socket 5831 . -viewer_socket_port <port> - Port number to use for socket 5832 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5833 5834 Level: beginner 5835 5836 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5837 @*/ 5838 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5839 { 5840 static PetscInt inassm = 0; 5841 PetscBool flg = PETSC_FALSE; 5842 5843 PetscFunctionBegin; 5844 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5845 PetscValidType(mat, 1); 5846 5847 inassm++; 5848 MatAssemblyEnd_InUse++; 5849 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5850 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5851 PetscTryTypeMethod(mat, assemblyend, type); 5852 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5853 } else PetscTryTypeMethod(mat, assemblyend, type); 5854 5855 /* Flush assembly is not a true assembly */ 5856 if (type != MAT_FLUSH_ASSEMBLY) { 5857 if (mat->num_ass) { 5858 if (!mat->symmetry_eternal) { 5859 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5860 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5861 } 5862 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5863 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5864 } 5865 mat->num_ass++; 5866 mat->assembled = PETSC_TRUE; 5867 mat->ass_nonzerostate = mat->nonzerostate; 5868 } 5869 5870 mat->insertmode = NOT_SET_VALUES; 5871 MatAssemblyEnd_InUse--; 5872 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5873 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5874 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5875 5876 if (mat->checksymmetryonassembly) { 5877 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5878 if (flg) { 5879 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5880 } else { 5881 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5882 } 5883 } 5884 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5885 } 5886 inassm--; 5887 PetscFunctionReturn(PETSC_SUCCESS); 5888 } 5889 5890 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5891 /*@ 5892 MatSetOption - Sets a parameter option for a matrix. Some options 5893 may be specific to certain storage formats. Some options 5894 determine how values will be inserted (or added). Sorted, 5895 row-oriented input will generally assemble the fastest. The default 5896 is row-oriented. 5897 5898 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5899 5900 Input Parameters: 5901 + mat - the matrix 5902 . op - the option, one of those listed below (and possibly others), 5903 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5904 5905 Options Describing Matrix Structure: 5906 + `MAT_SPD` - symmetric positive definite 5907 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5908 . `MAT_HERMITIAN` - transpose is the complex conjugation 5909 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5910 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5911 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5912 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5913 5914 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5915 do not need to be computed (usually at a high cost) 5916 5917 Options For Use with `MatSetValues()`: 5918 Insert a logically dense subblock, which can be 5919 . `MAT_ROW_ORIENTED` - row-oriented (default) 5920 5921 These options reflect the data you pass in with `MatSetValues()`; it has 5922 nothing to do with how the data is stored internally in the matrix 5923 data structure. 5924 5925 When (re)assembling a matrix, we can restrict the input for 5926 efficiency/debugging purposes. These options include 5927 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5928 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5929 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5930 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5931 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5932 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5933 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5934 performance for very large process counts. 5935 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5936 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5937 functions, instead sending only neighbor messages. 5938 5939 Level: intermediate 5940 5941 Notes: 5942 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5943 5944 Some options are relevant only for particular matrix types and 5945 are thus ignored by others. Other options are not supported by 5946 certain matrix types and will generate an error message if set. 5947 5948 If using Fortran to compute a matrix, one may need to 5949 use the column-oriented option (or convert to the row-oriented 5950 format). 5951 5952 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5953 that would generate a new entry in the nonzero structure is instead 5954 ignored. Thus, if memory has not already been allocated for this particular 5955 data, then the insertion is ignored. For dense matrices, in which 5956 the entire array is allocated, no entries are ever ignored. 5957 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5958 5959 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5960 that would generate a new entry in the nonzero structure instead produces 5961 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 5962 5963 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5964 that would generate a new entry that has not been preallocated will 5965 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5966 only.) This is a useful flag when debugging matrix memory preallocation. 5967 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5968 5969 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5970 other processors should be dropped, rather than stashed. 5971 This is useful if you know that the "owning" processor is also 5972 always generating the correct matrix entries, so that PETSc need 5973 not transfer duplicate entries generated on another processor. 5974 5975 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5976 searches during matrix assembly. When this flag is set, the hash table 5977 is created during the first matrix assembly. This hash table is 5978 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5979 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5980 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5981 supported by `MATMPIBAIJ` format only. 5982 5983 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5984 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 5985 5986 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5987 a zero location in the matrix 5988 5989 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5990 5991 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5992 zero row routines and thus improves performance for very large process counts. 5993 5994 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5995 part of the matrix (since they should match the upper triangular part). 5996 5997 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5998 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 5999 with finite difference schemes with non-periodic boundary conditions. 6000 6001 Developer Note: 6002 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6003 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6004 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6005 not changed. 6006 6007 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6008 @*/ 6009 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6010 { 6011 PetscFunctionBegin; 6012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6013 if (op > 0) { 6014 PetscValidLogicalCollectiveEnum(mat, op, 2); 6015 PetscValidLogicalCollectiveBool(mat, flg, 3); 6016 } 6017 6018 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); 6019 6020 switch (op) { 6021 case MAT_FORCE_DIAGONAL_ENTRIES: 6022 mat->force_diagonals = flg; 6023 PetscFunctionReturn(PETSC_SUCCESS); 6024 case MAT_NO_OFF_PROC_ENTRIES: 6025 mat->nooffprocentries = flg; 6026 PetscFunctionReturn(PETSC_SUCCESS); 6027 case MAT_SUBSET_OFF_PROC_ENTRIES: 6028 mat->assembly_subset = flg; 6029 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6030 #if !defined(PETSC_HAVE_MPIUNI) 6031 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6032 #endif 6033 mat->stash.first_assembly_done = PETSC_FALSE; 6034 } 6035 PetscFunctionReturn(PETSC_SUCCESS); 6036 case MAT_NO_OFF_PROC_ZERO_ROWS: 6037 mat->nooffproczerorows = flg; 6038 PetscFunctionReturn(PETSC_SUCCESS); 6039 case MAT_SPD: 6040 if (flg) { 6041 mat->spd = PETSC_BOOL3_TRUE; 6042 mat->symmetric = PETSC_BOOL3_TRUE; 6043 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6044 } else { 6045 mat->spd = PETSC_BOOL3_FALSE; 6046 } 6047 break; 6048 case MAT_SYMMETRIC: 6049 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6050 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6051 #if !defined(PETSC_USE_COMPLEX) 6052 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6053 #endif 6054 break; 6055 case MAT_HERMITIAN: 6056 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6057 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6058 #if !defined(PETSC_USE_COMPLEX) 6059 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6060 #endif 6061 break; 6062 case MAT_STRUCTURALLY_SYMMETRIC: 6063 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6064 break; 6065 case MAT_SYMMETRY_ETERNAL: 6066 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"); 6067 mat->symmetry_eternal = flg; 6068 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6069 break; 6070 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6071 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"); 6072 mat->structural_symmetry_eternal = flg; 6073 break; 6074 case MAT_SPD_ETERNAL: 6075 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"); 6076 mat->spd_eternal = flg; 6077 if (flg) { 6078 mat->structural_symmetry_eternal = PETSC_TRUE; 6079 mat->symmetry_eternal = PETSC_TRUE; 6080 } 6081 break; 6082 case MAT_STRUCTURE_ONLY: 6083 mat->structure_only = flg; 6084 break; 6085 case MAT_SORTED_FULL: 6086 mat->sortedfull = flg; 6087 break; 6088 default: 6089 break; 6090 } 6091 PetscTryTypeMethod(mat, setoption, op, flg); 6092 PetscFunctionReturn(PETSC_SUCCESS); 6093 } 6094 6095 /*@ 6096 MatGetOption - Gets a parameter option that has been set for a matrix. 6097 6098 Logically Collective 6099 6100 Input Parameters: 6101 + mat - the matrix 6102 - op - the option, this only responds to certain options, check the code for which ones 6103 6104 Output Parameter: 6105 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6106 6107 Level: intermediate 6108 6109 Notes: 6110 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6111 6112 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6113 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6114 6115 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6116 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6117 @*/ 6118 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6119 { 6120 PetscFunctionBegin; 6121 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6122 PetscValidType(mat, 1); 6123 6124 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); 6125 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()"); 6126 6127 switch (op) { 6128 case MAT_NO_OFF_PROC_ENTRIES: 6129 *flg = mat->nooffprocentries; 6130 break; 6131 case MAT_NO_OFF_PROC_ZERO_ROWS: 6132 *flg = mat->nooffproczerorows; 6133 break; 6134 case MAT_SYMMETRIC: 6135 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6136 break; 6137 case MAT_HERMITIAN: 6138 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6139 break; 6140 case MAT_STRUCTURALLY_SYMMETRIC: 6141 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6142 break; 6143 case MAT_SPD: 6144 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6145 break; 6146 case MAT_SYMMETRY_ETERNAL: 6147 *flg = mat->symmetry_eternal; 6148 break; 6149 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6150 *flg = mat->symmetry_eternal; 6151 break; 6152 default: 6153 break; 6154 } 6155 PetscFunctionReturn(PETSC_SUCCESS); 6156 } 6157 6158 /*@ 6159 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6160 this routine retains the old nonzero structure. 6161 6162 Logically Collective 6163 6164 Input Parameter: 6165 . mat - the matrix 6166 6167 Level: intermediate 6168 6169 Note: 6170 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. 6171 See the Performance chapter of the users manual for information on preallocating matrices. 6172 6173 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6174 @*/ 6175 PetscErrorCode MatZeroEntries(Mat mat) 6176 { 6177 PetscFunctionBegin; 6178 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6179 PetscValidType(mat, 1); 6180 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6181 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"); 6182 MatCheckPreallocated(mat, 1); 6183 6184 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6185 PetscUseTypeMethod(mat, zeroentries); 6186 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6187 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6188 PetscFunctionReturn(PETSC_SUCCESS); 6189 } 6190 6191 /*@ 6192 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6193 of a set of rows and columns of a matrix. 6194 6195 Collective 6196 6197 Input Parameters: 6198 + mat - the matrix 6199 . numRows - the number of rows/columns to zero 6200 . rows - the global row indices 6201 . diag - value put in the diagonal of the eliminated rows 6202 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6203 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6204 6205 Level: intermediate 6206 6207 Notes: 6208 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6209 6210 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6211 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 6212 6213 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6214 Krylov method to take advantage of the known solution on the zeroed rows. 6215 6216 For the parallel case, all processes that share the matrix (i.e., 6217 those in the communicator used for matrix creation) MUST call this 6218 routine, regardless of whether any rows being zeroed are owned by 6219 them. 6220 6221 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6222 removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously 6223 missing. 6224 6225 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6226 list only rows local to itself). 6227 6228 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6229 6230 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6231 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6232 @*/ 6233 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6234 { 6235 PetscFunctionBegin; 6236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6237 PetscValidType(mat, 1); 6238 if (numRows) PetscAssertPointer(rows, 3); 6239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6240 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6241 MatCheckPreallocated(mat, 1); 6242 6243 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6244 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6245 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6246 PetscFunctionReturn(PETSC_SUCCESS); 6247 } 6248 6249 /*@ 6250 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6251 of a set of rows and columns of a matrix. 6252 6253 Collective 6254 6255 Input Parameters: 6256 + mat - the matrix 6257 . is - the rows to zero 6258 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6259 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6260 - b - optional vector of right-hand side, that will be adjusted by provided solution 6261 6262 Level: intermediate 6263 6264 Note: 6265 See `MatZeroRowsColumns()` for details on how this routine operates. 6266 6267 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6268 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6269 @*/ 6270 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6271 { 6272 PetscInt numRows; 6273 const PetscInt *rows; 6274 6275 PetscFunctionBegin; 6276 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6277 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6278 PetscValidType(mat, 1); 6279 PetscValidType(is, 2); 6280 PetscCall(ISGetLocalSize(is, &numRows)); 6281 PetscCall(ISGetIndices(is, &rows)); 6282 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6283 PetscCall(ISRestoreIndices(is, &rows)); 6284 PetscFunctionReturn(PETSC_SUCCESS); 6285 } 6286 6287 /*@ 6288 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6289 of a set of rows of a matrix. 6290 6291 Collective 6292 6293 Input Parameters: 6294 + mat - the matrix 6295 . numRows - the number of rows to zero 6296 . rows - the global row indices 6297 . diag - value put in the diagonal of the zeroed rows 6298 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6299 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6300 6301 Level: intermediate 6302 6303 Notes: 6304 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6305 6306 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6307 6308 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6309 Krylov method to take advantage of the known solution on the zeroed rows. 6310 6311 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) 6312 from the matrix. 6313 6314 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6315 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 6316 formats this does not alter the nonzero structure. 6317 6318 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6319 of the matrix is not changed the values are 6320 merely zeroed. 6321 6322 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6323 formats can optionally remove the main diagonal entry from the 6324 nonzero structure as well, by passing 0.0 as the final argument). 6325 6326 For the parallel case, all processes that share the matrix (i.e., 6327 those in the communicator used for matrix creation) MUST call this 6328 routine, regardless of whether any rows being zeroed are owned by 6329 them. 6330 6331 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6332 list only rows local to itself). 6333 6334 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6335 owns that are to be zeroed. This saves a global synchronization in the implementation. 6336 6337 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6338 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6339 @*/ 6340 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6341 { 6342 PetscFunctionBegin; 6343 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6344 PetscValidType(mat, 1); 6345 if (numRows) PetscAssertPointer(rows, 3); 6346 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6347 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6348 MatCheckPreallocated(mat, 1); 6349 6350 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6351 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6352 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6353 PetscFunctionReturn(PETSC_SUCCESS); 6354 } 6355 6356 /*@ 6357 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6358 of a set of rows of a matrix. 6359 6360 Collective 6361 6362 Input Parameters: 6363 + mat - the matrix 6364 . is - index set of rows to remove (if `NULL` then no row is removed) 6365 . diag - value put in all diagonals of eliminated rows 6366 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6367 - b - optional vector of right-hand side, that will be adjusted by provided solution 6368 6369 Level: intermediate 6370 6371 Note: 6372 See `MatZeroRows()` for details on how this routine operates. 6373 6374 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6375 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6376 @*/ 6377 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6378 { 6379 PetscInt numRows = 0; 6380 const PetscInt *rows = NULL; 6381 6382 PetscFunctionBegin; 6383 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6384 PetscValidType(mat, 1); 6385 if (is) { 6386 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6387 PetscCall(ISGetLocalSize(is, &numRows)); 6388 PetscCall(ISGetIndices(is, &rows)); 6389 } 6390 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6391 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6392 PetscFunctionReturn(PETSC_SUCCESS); 6393 } 6394 6395 /*@ 6396 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6397 of a set of rows of a matrix. These rows must be local to the process. 6398 6399 Collective 6400 6401 Input Parameters: 6402 + mat - the matrix 6403 . numRows - the number of rows to remove 6404 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6405 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6406 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6407 - b - optional vector of right-hand side, that will be adjusted by provided solution 6408 6409 Level: intermediate 6410 6411 Notes: 6412 See `MatZeroRows()` for details on how this routine operates. 6413 6414 The grid coordinates are across the entire grid, not just the local portion 6415 6416 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6417 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6418 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6419 `DM_BOUNDARY_PERIODIC` boundary type. 6420 6421 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 6422 a single value per point) you can skip filling those indices. 6423 6424 Fortran Note: 6425 `idxm` and `idxn` should be declared as 6426 $ MatStencil idxm(4, m) 6427 and the values inserted using 6428 .vb 6429 idxm(MatStencil_i, 1) = i 6430 idxm(MatStencil_j, 1) = j 6431 idxm(MatStencil_k, 1) = k 6432 idxm(MatStencil_c, 1) = c 6433 etc 6434 .ve 6435 6436 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6437 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6438 @*/ 6439 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6440 { 6441 PetscInt dim = mat->stencil.dim; 6442 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6443 PetscInt *dims = mat->stencil.dims + 1; 6444 PetscInt *starts = mat->stencil.starts; 6445 PetscInt *dxm = (PetscInt *)rows; 6446 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6447 6448 PetscFunctionBegin; 6449 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6450 PetscValidType(mat, 1); 6451 if (numRows) PetscAssertPointer(rows, 3); 6452 6453 PetscCall(PetscMalloc1(numRows, &jdxm)); 6454 for (i = 0; i < numRows; ++i) { 6455 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6456 for (j = 0; j < 3 - sdim; ++j) dxm++; 6457 /* Local index in X dir */ 6458 tmp = *dxm++ - starts[0]; 6459 /* Loop over remaining dimensions */ 6460 for (j = 0; j < dim - 1; ++j) { 6461 /* If nonlocal, set index to be negative */ 6462 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6463 /* Update local index */ 6464 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6465 } 6466 /* Skip component slot if necessary */ 6467 if (mat->stencil.noc) dxm++; 6468 /* Local row number */ 6469 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6470 } 6471 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6472 PetscCall(PetscFree(jdxm)); 6473 PetscFunctionReturn(PETSC_SUCCESS); 6474 } 6475 6476 /*@ 6477 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6478 of a set of rows and columns of a matrix. 6479 6480 Collective 6481 6482 Input Parameters: 6483 + mat - the matrix 6484 . numRows - the number of rows/columns to remove 6485 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6486 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6487 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6488 - b - optional vector of right-hand side, that will be adjusted by provided solution 6489 6490 Level: intermediate 6491 6492 Notes: 6493 See `MatZeroRowsColumns()` for details on how this routine operates. 6494 6495 The grid coordinates are across the entire grid, not just the local portion 6496 6497 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6498 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6499 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6500 `DM_BOUNDARY_PERIODIC` boundary type. 6501 6502 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 6503 a single value per point) you can skip filling those indices. 6504 6505 Fortran Note: 6506 `idxm` and `idxn` should be declared as 6507 $ MatStencil idxm(4, m) 6508 and the values inserted using 6509 .vb 6510 idxm(MatStencil_i, 1) = i 6511 idxm(MatStencil_j, 1) = j 6512 idxm(MatStencil_k, 1) = k 6513 idxm(MatStencil_c, 1) = c 6514 etc 6515 .ve 6516 6517 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6518 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6519 @*/ 6520 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6521 { 6522 PetscInt dim = mat->stencil.dim; 6523 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6524 PetscInt *dims = mat->stencil.dims + 1; 6525 PetscInt *starts = mat->stencil.starts; 6526 PetscInt *dxm = (PetscInt *)rows; 6527 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6528 6529 PetscFunctionBegin; 6530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6531 PetscValidType(mat, 1); 6532 if (numRows) PetscAssertPointer(rows, 3); 6533 6534 PetscCall(PetscMalloc1(numRows, &jdxm)); 6535 for (i = 0; i < numRows; ++i) { 6536 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6537 for (j = 0; j < 3 - sdim; ++j) dxm++; 6538 /* Local index in X dir */ 6539 tmp = *dxm++ - starts[0]; 6540 /* Loop over remaining dimensions */ 6541 for (j = 0; j < dim - 1; ++j) { 6542 /* If nonlocal, set index to be negative */ 6543 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6544 /* Update local index */ 6545 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6546 } 6547 /* Skip component slot if necessary */ 6548 if (mat->stencil.noc) dxm++; 6549 /* Local row number */ 6550 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6551 } 6552 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6553 PetscCall(PetscFree(jdxm)); 6554 PetscFunctionReturn(PETSC_SUCCESS); 6555 } 6556 6557 /*@C 6558 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6559 of a set of rows of a matrix; using local numbering of rows. 6560 6561 Collective 6562 6563 Input Parameters: 6564 + mat - the matrix 6565 . numRows - the number of rows to remove 6566 . rows - the local row indices 6567 . diag - value put in all diagonals of eliminated rows 6568 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6569 - b - optional vector of right-hand side, that will be adjusted by provided solution 6570 6571 Level: intermediate 6572 6573 Notes: 6574 Before calling `MatZeroRowsLocal()`, the user must first set the 6575 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6576 6577 See `MatZeroRows()` for details on how this routine operates. 6578 6579 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6580 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6581 @*/ 6582 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6583 { 6584 PetscFunctionBegin; 6585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6586 PetscValidType(mat, 1); 6587 if (numRows) PetscAssertPointer(rows, 3); 6588 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6589 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6590 MatCheckPreallocated(mat, 1); 6591 6592 if (mat->ops->zerorowslocal) { 6593 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6594 } else { 6595 IS is, newis; 6596 const PetscInt *newRows; 6597 6598 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6599 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6600 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6601 PetscCall(ISGetIndices(newis, &newRows)); 6602 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6603 PetscCall(ISRestoreIndices(newis, &newRows)); 6604 PetscCall(ISDestroy(&newis)); 6605 PetscCall(ISDestroy(&is)); 6606 } 6607 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6608 PetscFunctionReturn(PETSC_SUCCESS); 6609 } 6610 6611 /*@ 6612 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6613 of a set of rows 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 `MatZeroRowsLocalIS()`, 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 `MatZeroRows()` for details on how this routine operates. 6631 6632 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6633 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6634 @*/ 6635 PetscErrorCode MatZeroRowsLocalIS(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(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6651 PetscCall(ISRestoreIndices(is, &rows)); 6652 PetscFunctionReturn(PETSC_SUCCESS); 6653 } 6654 6655 /*@ 6656 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6657 of a set of rows and columns of a matrix; using local numbering of rows. 6658 6659 Collective 6660 6661 Input Parameters: 6662 + mat - the matrix 6663 . numRows - the number of rows to remove 6664 . rows - the global row indices 6665 . diag - value put in all diagonals of eliminated rows 6666 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6667 - b - optional vector of right-hand side, that will be adjusted by provided solution 6668 6669 Level: intermediate 6670 6671 Notes: 6672 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6673 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6674 6675 See `MatZeroRowsColumns()` for details on how this routine operates. 6676 6677 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6678 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6679 @*/ 6680 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6681 { 6682 IS is, newis; 6683 const PetscInt *newRows; 6684 6685 PetscFunctionBegin; 6686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6687 PetscValidType(mat, 1); 6688 if (numRows) PetscAssertPointer(rows, 3); 6689 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6690 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6691 MatCheckPreallocated(mat, 1); 6692 6693 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6694 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6695 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6696 PetscCall(ISGetIndices(newis, &newRows)); 6697 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6698 PetscCall(ISRestoreIndices(newis, &newRows)); 6699 PetscCall(ISDestroy(&newis)); 6700 PetscCall(ISDestroy(&is)); 6701 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6702 PetscFunctionReturn(PETSC_SUCCESS); 6703 } 6704 6705 /*@ 6706 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6707 of a set of rows and columns of a matrix; using local numbering of rows. 6708 6709 Collective 6710 6711 Input Parameters: 6712 + mat - the matrix 6713 . is - index set of rows to remove 6714 . diag - value put in all diagonals of eliminated rows 6715 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6716 - b - optional vector of right-hand side, that will be adjusted by provided solution 6717 6718 Level: intermediate 6719 6720 Notes: 6721 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6722 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6723 6724 See `MatZeroRowsColumns()` for details on how this routine operates. 6725 6726 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6727 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6728 @*/ 6729 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6730 { 6731 PetscInt numRows; 6732 const PetscInt *rows; 6733 6734 PetscFunctionBegin; 6735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6736 PetscValidType(mat, 1); 6737 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6738 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6739 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6740 MatCheckPreallocated(mat, 1); 6741 6742 PetscCall(ISGetLocalSize(is, &numRows)); 6743 PetscCall(ISGetIndices(is, &rows)); 6744 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6745 PetscCall(ISRestoreIndices(is, &rows)); 6746 PetscFunctionReturn(PETSC_SUCCESS); 6747 } 6748 6749 /*@C 6750 MatGetSize - Returns the numbers of rows and columns in a matrix. 6751 6752 Not Collective 6753 6754 Input Parameter: 6755 . mat - the matrix 6756 6757 Output Parameters: 6758 + m - the number of global rows 6759 - n - the number of global columns 6760 6761 Level: beginner 6762 6763 Note: 6764 Both output parameters can be `NULL` on input. 6765 6766 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6767 @*/ 6768 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6769 { 6770 PetscFunctionBegin; 6771 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6772 if (m) *m = mat->rmap->N; 6773 if (n) *n = mat->cmap->N; 6774 PetscFunctionReturn(PETSC_SUCCESS); 6775 } 6776 6777 /*@C 6778 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6779 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6780 6781 Not Collective 6782 6783 Input Parameter: 6784 . mat - the matrix 6785 6786 Output Parameters: 6787 + m - the number of local rows, use `NULL` to not obtain this value 6788 - n - the number of local columns, use `NULL` to not obtain this value 6789 6790 Level: beginner 6791 6792 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6793 @*/ 6794 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6795 { 6796 PetscFunctionBegin; 6797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6798 if (m) PetscAssertPointer(m, 2); 6799 if (n) PetscAssertPointer(n, 3); 6800 if (m) *m = mat->rmap->n; 6801 if (n) *n = mat->cmap->n; 6802 PetscFunctionReturn(PETSC_SUCCESS); 6803 } 6804 6805 /*@ 6806 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6807 vector one multiplies this matrix by that are owned by this processor. 6808 6809 Not Collective, unless matrix has not been allocated, then collective 6810 6811 Input Parameter: 6812 . mat - the matrix 6813 6814 Output Parameters: 6815 + m - the global index of the first local column, use `NULL` to not obtain this value 6816 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6817 6818 Level: developer 6819 6820 Notes: 6821 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6822 6823 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6824 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6825 6826 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6827 the local values in the matrix. 6828 6829 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6830 Layouts](sec_matlayout) for details on matrix layouts. 6831 6832 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6833 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6834 @*/ 6835 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6836 { 6837 PetscFunctionBegin; 6838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6839 PetscValidType(mat, 1); 6840 if (m) PetscAssertPointer(m, 2); 6841 if (n) PetscAssertPointer(n, 3); 6842 MatCheckPreallocated(mat, 1); 6843 if (m) *m = mat->cmap->rstart; 6844 if (n) *n = mat->cmap->rend; 6845 PetscFunctionReturn(PETSC_SUCCESS); 6846 } 6847 6848 /*@C 6849 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6850 this MPI process. 6851 6852 Not Collective 6853 6854 Input Parameter: 6855 . mat - the matrix 6856 6857 Output Parameters: 6858 + m - the global index of the first local row, use `NULL` to not obtain this value 6859 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6860 6861 Level: beginner 6862 6863 Notes: 6864 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6865 6866 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6867 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6868 6869 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6870 the local values in the matrix. 6871 6872 The high argument is one more than the last element stored locally. 6873 6874 For all matrices it returns the range of matrix rows associated with rows of a vector that 6875 would contain the result of a matrix vector product with this matrix. See [Matrix 6876 Layouts](sec_matlayout) for details on matrix layouts. 6877 6878 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6879 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6880 @*/ 6881 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6882 { 6883 PetscFunctionBegin; 6884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6885 PetscValidType(mat, 1); 6886 if (m) PetscAssertPointer(m, 2); 6887 if (n) PetscAssertPointer(n, 3); 6888 MatCheckPreallocated(mat, 1); 6889 if (m) *m = mat->rmap->rstart; 6890 if (n) *n = mat->rmap->rend; 6891 PetscFunctionReturn(PETSC_SUCCESS); 6892 } 6893 6894 /*@C 6895 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6896 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6897 6898 Not Collective, unless matrix has not been allocated 6899 6900 Input Parameter: 6901 . mat - the matrix 6902 6903 Output Parameter: 6904 . ranges - start of each processors portion plus one more than the total length at the end 6905 6906 Level: beginner 6907 6908 Notes: 6909 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6910 6911 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6912 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6913 6914 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6915 the local values in the matrix. 6916 6917 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6918 would contain the result of a matrix vector product with this matrix. See [Matrix 6919 Layouts](sec_matlayout) for details on matrix layouts. 6920 6921 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6922 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6923 `DMDAGetGhostCorners()`, `DM` 6924 @*/ 6925 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6926 { 6927 PetscFunctionBegin; 6928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6929 PetscValidType(mat, 1); 6930 MatCheckPreallocated(mat, 1); 6931 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6932 PetscFunctionReturn(PETSC_SUCCESS); 6933 } 6934 6935 /*@C 6936 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6937 vector one multiplies this vector by that are owned by each processor. 6938 6939 Not Collective, unless matrix has not been allocated 6940 6941 Input Parameter: 6942 . mat - the matrix 6943 6944 Output Parameter: 6945 . ranges - start of each processors portion plus one more than the total length at the end 6946 6947 Level: beginner 6948 6949 Notes: 6950 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6951 6952 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6953 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6954 6955 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6956 the local values in the matrix. 6957 6958 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6959 Layouts](sec_matlayout) for details on matrix layouts. 6960 6961 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6962 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6963 `DMDAGetGhostCorners()`, `DM` 6964 @*/ 6965 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6966 { 6967 PetscFunctionBegin; 6968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6969 PetscValidType(mat, 1); 6970 MatCheckPreallocated(mat, 1); 6971 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6972 PetscFunctionReturn(PETSC_SUCCESS); 6973 } 6974 6975 /*@C 6976 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6977 6978 Not Collective 6979 6980 Input Parameter: 6981 . A - matrix 6982 6983 Output Parameters: 6984 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6985 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6986 6987 Level: intermediate 6988 6989 Note: 6990 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6991 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6992 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6993 details on matrix layouts. 6994 6995 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumns()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6996 @*/ 6997 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6998 { 6999 PetscErrorCode (*f)(Mat, IS *, IS *); 7000 7001 PetscFunctionBegin; 7002 MatCheckPreallocated(A, 1); 7003 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7004 if (f) { 7005 PetscCall((*f)(A, rows, cols)); 7006 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7007 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7008 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7009 } 7010 PetscFunctionReturn(PETSC_SUCCESS); 7011 } 7012 7013 /*@C 7014 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7015 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7016 to complete the factorization. 7017 7018 Collective 7019 7020 Input Parameters: 7021 + fact - the factorized matrix obtained with `MatGetFactor()` 7022 . mat - the matrix 7023 . row - row permutation 7024 . col - column permutation 7025 - info - structure containing 7026 .vb 7027 levels - number of levels of fill. 7028 expected fill - as ratio of original fill. 7029 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7030 missing diagonal entries) 7031 .ve 7032 7033 Level: developer 7034 7035 Notes: 7036 See [Matrix Factorization](sec_matfactor) for additional information. 7037 7038 Most users should employ the `KSP` interface for linear solvers 7039 instead of working directly with matrix algebra routines such as this. 7040 See, e.g., `KSPCreate()`. 7041 7042 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7043 7044 Developer Note: 7045 The Fortran interface is not autogenerated as the 7046 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7047 7048 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7049 `MatGetOrdering()`, `MatFactorInfo` 7050 @*/ 7051 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7052 { 7053 PetscFunctionBegin; 7054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7055 PetscValidType(mat, 2); 7056 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7057 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7058 PetscAssertPointer(info, 5); 7059 PetscAssertPointer(fact, 1); 7060 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7061 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7062 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7063 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7064 MatCheckPreallocated(mat, 2); 7065 7066 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7067 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7068 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7069 PetscFunctionReturn(PETSC_SUCCESS); 7070 } 7071 7072 /*@C 7073 MatICCFactorSymbolic - Performs symbolic incomplete 7074 Cholesky factorization for a symmetric matrix. Use 7075 `MatCholeskyFactorNumeric()` to complete the factorization. 7076 7077 Collective 7078 7079 Input Parameters: 7080 + fact - the factorized matrix obtained with `MatGetFactor()` 7081 . mat - the matrix to be factored 7082 . perm - row and column permutation 7083 - info - structure containing 7084 .vb 7085 levels - number of levels of fill. 7086 expected fill - as ratio of original fill. 7087 .ve 7088 7089 Level: developer 7090 7091 Notes: 7092 Most users should employ the `KSP` interface for linear solvers 7093 instead of working directly with matrix algebra routines such as this. 7094 See, e.g., `KSPCreate()`. 7095 7096 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7097 7098 Developer Note: 7099 The Fortran interface is not autogenerated as the 7100 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7101 7102 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7103 @*/ 7104 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7105 { 7106 PetscFunctionBegin; 7107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7108 PetscValidType(mat, 2); 7109 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7110 PetscAssertPointer(info, 4); 7111 PetscAssertPointer(fact, 1); 7112 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7113 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7114 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7115 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7116 MatCheckPreallocated(mat, 2); 7117 7118 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7119 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7120 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7121 PetscFunctionReturn(PETSC_SUCCESS); 7122 } 7123 7124 /*@C 7125 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7126 points to an array of valid matrices, they may be reused to store the new 7127 submatrices. 7128 7129 Collective 7130 7131 Input Parameters: 7132 + mat - the matrix 7133 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7134 . irow - index set of rows to extract 7135 . icol - index set of columns to extract 7136 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7137 7138 Output Parameter: 7139 . submat - the array of submatrices 7140 7141 Level: advanced 7142 7143 Notes: 7144 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7145 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7146 to extract a parallel submatrix. 7147 7148 Some matrix types place restrictions on the row and column 7149 indices, such as that they be sorted or that they be equal to each other. 7150 7151 The index sets may not have duplicate entries. 7152 7153 When extracting submatrices from a parallel matrix, each processor can 7154 form a different submatrix by setting the rows and columns of its 7155 individual index sets according to the local submatrix desired. 7156 7157 When finished using the submatrices, the user should destroy 7158 them with `MatDestroySubMatrices()`. 7159 7160 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7161 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7162 7163 This routine creates the matrices in submat; you should NOT create them before 7164 calling it. It also allocates the array of matrix pointers submat. 7165 7166 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7167 request one row/column in a block, they must request all rows/columns that are in 7168 that block. For example, if the block size is 2 you cannot request just row 0 and 7169 column 0. 7170 7171 Fortran Note: 7172 The Fortran interface is slightly different from that given below; it 7173 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7174 7175 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7176 @*/ 7177 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7178 { 7179 PetscInt i; 7180 PetscBool eq; 7181 7182 PetscFunctionBegin; 7183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7184 PetscValidType(mat, 1); 7185 if (n) { 7186 PetscAssertPointer(irow, 3); 7187 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7188 PetscAssertPointer(icol, 4); 7189 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7190 } 7191 PetscAssertPointer(submat, 6); 7192 if (n && scall == MAT_REUSE_MATRIX) { 7193 PetscAssertPointer(*submat, 6); 7194 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7195 } 7196 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7197 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7198 MatCheckPreallocated(mat, 1); 7199 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7200 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7201 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7202 for (i = 0; i < n; i++) { 7203 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7204 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7205 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7206 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7207 if (mat->boundtocpu && mat->bindingpropagates) { 7208 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7209 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7210 } 7211 #endif 7212 } 7213 PetscFunctionReturn(PETSC_SUCCESS); 7214 } 7215 7216 /*@C 7217 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7218 7219 Collective 7220 7221 Input Parameters: 7222 + mat - the matrix 7223 . n - the number of submatrixes to be extracted 7224 . irow - index set of rows to extract 7225 . icol - index set of columns to extract 7226 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7227 7228 Output Parameter: 7229 . submat - the array of submatrices 7230 7231 Level: advanced 7232 7233 Note: 7234 This is used by `PCGASM` 7235 7236 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7237 @*/ 7238 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7239 { 7240 PetscInt i; 7241 PetscBool eq; 7242 7243 PetscFunctionBegin; 7244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7245 PetscValidType(mat, 1); 7246 if (n) { 7247 PetscAssertPointer(irow, 3); 7248 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7249 PetscAssertPointer(icol, 4); 7250 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7251 } 7252 PetscAssertPointer(submat, 6); 7253 if (n && scall == MAT_REUSE_MATRIX) { 7254 PetscAssertPointer(*submat, 6); 7255 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7256 } 7257 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7258 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7259 MatCheckPreallocated(mat, 1); 7260 7261 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7262 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7263 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7264 for (i = 0; i < n; i++) { 7265 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7266 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7267 } 7268 PetscFunctionReturn(PETSC_SUCCESS); 7269 } 7270 7271 /*@C 7272 MatDestroyMatrices - Destroys an array of matrices. 7273 7274 Collective 7275 7276 Input Parameters: 7277 + n - the number of local matrices 7278 - mat - the matrices (this is a pointer to the array of matrices) 7279 7280 Level: advanced 7281 7282 Note: 7283 Frees not only the matrices, but also the array that contains the matrices 7284 7285 Fortran Note: 7286 This does not free the array. 7287 7288 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7289 @*/ 7290 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7291 { 7292 PetscInt i; 7293 7294 PetscFunctionBegin; 7295 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7296 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7297 PetscAssertPointer(mat, 2); 7298 7299 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7300 7301 /* memory is allocated even if n = 0 */ 7302 PetscCall(PetscFree(*mat)); 7303 PetscFunctionReturn(PETSC_SUCCESS); 7304 } 7305 7306 /*@C 7307 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7308 7309 Collective 7310 7311 Input Parameters: 7312 + n - the number of local matrices 7313 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7314 sequence of `MatCreateSubMatrices()`) 7315 7316 Level: advanced 7317 7318 Note: 7319 Frees not only the matrices, but also the array that contains the matrices 7320 7321 Fortran Note: 7322 This does not free the array. 7323 7324 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7325 @*/ 7326 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7327 { 7328 Mat mat0; 7329 7330 PetscFunctionBegin; 7331 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7332 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7333 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7334 PetscAssertPointer(mat, 2); 7335 7336 mat0 = (*mat)[0]; 7337 if (mat0 && mat0->ops->destroysubmatrices) { 7338 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7339 } else { 7340 PetscCall(MatDestroyMatrices(n, mat)); 7341 } 7342 PetscFunctionReturn(PETSC_SUCCESS); 7343 } 7344 7345 /*@ 7346 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7347 7348 Collective 7349 7350 Input Parameter: 7351 . mat - the matrix 7352 7353 Output Parameter: 7354 . matstruct - the sequential matrix with the nonzero structure of `mat` 7355 7356 Level: developer 7357 7358 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7359 @*/ 7360 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7361 { 7362 PetscFunctionBegin; 7363 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7364 PetscAssertPointer(matstruct, 2); 7365 7366 PetscValidType(mat, 1); 7367 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7368 MatCheckPreallocated(mat, 1); 7369 7370 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7371 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7372 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7373 PetscFunctionReturn(PETSC_SUCCESS); 7374 } 7375 7376 /*@C 7377 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7378 7379 Collective 7380 7381 Input Parameter: 7382 . mat - the matrix 7383 7384 Level: advanced 7385 7386 Note: 7387 This is not needed, one can just call `MatDestroy()` 7388 7389 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7390 @*/ 7391 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7392 { 7393 PetscFunctionBegin; 7394 PetscAssertPointer(mat, 1); 7395 PetscCall(MatDestroy(mat)); 7396 PetscFunctionReturn(PETSC_SUCCESS); 7397 } 7398 7399 /*@ 7400 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7401 replaces the index sets by larger ones that represent submatrices with 7402 additional overlap. 7403 7404 Collective 7405 7406 Input Parameters: 7407 + mat - the matrix 7408 . n - the number of index sets 7409 . is - the array of index sets (these index sets will changed during the call) 7410 - ov - the additional overlap requested 7411 7412 Options Database Key: 7413 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7414 7415 Level: developer 7416 7417 Note: 7418 The computed overlap preserves the matrix block sizes when the blocks are square. 7419 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7420 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7421 7422 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7423 @*/ 7424 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7425 { 7426 PetscInt i, bs, cbs; 7427 7428 PetscFunctionBegin; 7429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7430 PetscValidType(mat, 1); 7431 PetscValidLogicalCollectiveInt(mat, n, 2); 7432 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7433 if (n) { 7434 PetscAssertPointer(is, 3); 7435 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7436 } 7437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7439 MatCheckPreallocated(mat, 1); 7440 7441 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7442 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7443 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7444 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7445 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7446 if (bs == cbs) { 7447 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7448 } 7449 PetscFunctionReturn(PETSC_SUCCESS); 7450 } 7451 7452 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7453 7454 /*@ 7455 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7456 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7457 additional overlap. 7458 7459 Collective 7460 7461 Input Parameters: 7462 + mat - the matrix 7463 . n - the number of index sets 7464 . is - the array of index sets (these index sets will changed during the call) 7465 - ov - the additional overlap requested 7466 7467 ` Options Database Key: 7468 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7469 7470 Level: developer 7471 7472 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7473 @*/ 7474 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7475 { 7476 PetscInt i; 7477 7478 PetscFunctionBegin; 7479 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7480 PetscValidType(mat, 1); 7481 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7482 if (n) { 7483 PetscAssertPointer(is, 3); 7484 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7485 } 7486 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7487 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7488 MatCheckPreallocated(mat, 1); 7489 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7490 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7491 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7492 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7493 PetscFunctionReturn(PETSC_SUCCESS); 7494 } 7495 7496 /*@ 7497 MatGetBlockSize - Returns the matrix block size. 7498 7499 Not Collective 7500 7501 Input Parameter: 7502 . mat - the matrix 7503 7504 Output Parameter: 7505 . bs - block size 7506 7507 Level: intermediate 7508 7509 Notes: 7510 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7511 7512 If the block size has not been set yet this routine returns 1. 7513 7514 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7515 @*/ 7516 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7517 { 7518 PetscFunctionBegin; 7519 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7520 PetscAssertPointer(bs, 2); 7521 *bs = PetscAbs(mat->rmap->bs); 7522 PetscFunctionReturn(PETSC_SUCCESS); 7523 } 7524 7525 /*@ 7526 MatGetBlockSizes - Returns the matrix block row and column sizes. 7527 7528 Not Collective 7529 7530 Input Parameter: 7531 . mat - the matrix 7532 7533 Output Parameters: 7534 + rbs - row block size 7535 - cbs - column block size 7536 7537 Level: intermediate 7538 7539 Notes: 7540 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7541 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7542 7543 If a block size has not been set yet this routine returns 1. 7544 7545 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7546 @*/ 7547 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7548 { 7549 PetscFunctionBegin; 7550 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7551 if (rbs) PetscAssertPointer(rbs, 2); 7552 if (cbs) PetscAssertPointer(cbs, 3); 7553 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7554 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7555 PetscFunctionReturn(PETSC_SUCCESS); 7556 } 7557 7558 /*@ 7559 MatSetBlockSize - Sets the matrix block size. 7560 7561 Logically Collective 7562 7563 Input Parameters: 7564 + mat - the matrix 7565 - bs - block size 7566 7567 Level: intermediate 7568 7569 Notes: 7570 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7571 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7572 7573 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7574 is compatible with the matrix local sizes. 7575 7576 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7577 @*/ 7578 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7579 { 7580 PetscFunctionBegin; 7581 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7582 PetscValidLogicalCollectiveInt(mat, bs, 2); 7583 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7584 PetscFunctionReturn(PETSC_SUCCESS); 7585 } 7586 7587 typedef struct { 7588 PetscInt n; 7589 IS *is; 7590 Mat *mat; 7591 PetscObjectState nonzerostate; 7592 Mat C; 7593 } EnvelopeData; 7594 7595 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7596 { 7597 EnvelopeData *edata = (EnvelopeData *)ptr; 7598 7599 PetscFunctionBegin; 7600 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7601 PetscCall(PetscFree(edata->is)); 7602 PetscCall(PetscFree(edata)); 7603 PetscFunctionReturn(PETSC_SUCCESS); 7604 } 7605 7606 /*@ 7607 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7608 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7609 7610 Collective 7611 7612 Input Parameter: 7613 . mat - the matrix 7614 7615 Level: intermediate 7616 7617 Notes: 7618 There can be zeros within the blocks 7619 7620 The blocks can overlap between processes, including laying on more than two processes 7621 7622 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7623 @*/ 7624 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7625 { 7626 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7627 PetscInt *diag, *odiag, sc; 7628 VecScatter scatter; 7629 PetscScalar *seqv; 7630 const PetscScalar *parv; 7631 const PetscInt *ia, *ja; 7632 PetscBool set, flag, done; 7633 Mat AA = mat, A; 7634 MPI_Comm comm; 7635 PetscMPIInt rank, size, tag; 7636 MPI_Status status; 7637 PetscContainer container; 7638 EnvelopeData *edata; 7639 Vec seq, par; 7640 IS isglobal; 7641 7642 PetscFunctionBegin; 7643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7644 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7645 if (!set || !flag) { 7646 /* TODO: only needs nonzero structure of transpose */ 7647 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7648 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7649 } 7650 PetscCall(MatAIJGetLocalMat(AA, &A)); 7651 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7652 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7653 7654 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7655 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7656 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7657 PetscCallMPI(MPI_Comm_size(comm, &size)); 7658 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7659 7660 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7661 7662 if (rank > 0) { 7663 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7664 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7665 } 7666 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7667 for (i = 0; i < n; i++) { 7668 env = PetscMax(env, ja[ia[i + 1] - 1]); 7669 II = rstart + i; 7670 if (env == II) { 7671 starts[lblocks] = tbs; 7672 sizes[lblocks++] = 1 + II - tbs; 7673 tbs = 1 + II; 7674 } 7675 } 7676 if (rank < size - 1) { 7677 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7678 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7679 } 7680 7681 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7682 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7683 PetscCall(MatDestroy(&A)); 7684 7685 PetscCall(PetscNew(&edata)); 7686 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7687 edata->n = lblocks; 7688 /* create IS needed for extracting blocks from the original matrix */ 7689 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7690 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7691 7692 /* Create the resulting inverse matrix structure with preallocation information */ 7693 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7694 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7695 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7696 PetscCall(MatSetType(edata->C, MATAIJ)); 7697 7698 /* Communicate the start and end of each row, from each block to the correct rank */ 7699 /* TODO: Use PetscSF instead of VecScatter */ 7700 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7701 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7702 PetscCall(VecGetArrayWrite(seq, &seqv)); 7703 for (PetscInt i = 0; i < lblocks; i++) { 7704 for (PetscInt j = 0; j < sizes[i]; j++) { 7705 seqv[cnt] = starts[i]; 7706 seqv[cnt + 1] = starts[i] + sizes[i]; 7707 cnt += 2; 7708 } 7709 } 7710 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7711 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7712 sc -= cnt; 7713 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7714 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7715 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7716 PetscCall(ISDestroy(&isglobal)); 7717 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7718 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7719 PetscCall(VecScatterDestroy(&scatter)); 7720 PetscCall(VecDestroy(&seq)); 7721 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7722 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7723 PetscCall(VecGetArrayRead(par, &parv)); 7724 cnt = 0; 7725 PetscCall(MatGetSize(mat, NULL, &n)); 7726 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7727 PetscInt start, end, d = 0, od = 0; 7728 7729 start = (PetscInt)PetscRealPart(parv[cnt]); 7730 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7731 cnt += 2; 7732 7733 if (start < cstart) { 7734 od += cstart - start + n - cend; 7735 d += cend - cstart; 7736 } else if (start < cend) { 7737 od += n - cend; 7738 d += cend - start; 7739 } else od += n - start; 7740 if (end <= cstart) { 7741 od -= cstart - end + n - cend; 7742 d -= cend - cstart; 7743 } else if (end < cend) { 7744 od -= n - cend; 7745 d -= cend - end; 7746 } else od -= n - end; 7747 7748 odiag[i] = od; 7749 diag[i] = d; 7750 } 7751 PetscCall(VecRestoreArrayRead(par, &parv)); 7752 PetscCall(VecDestroy(&par)); 7753 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7754 PetscCall(PetscFree2(diag, odiag)); 7755 PetscCall(PetscFree2(sizes, starts)); 7756 7757 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7758 PetscCall(PetscContainerSetPointer(container, edata)); 7759 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7760 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7761 PetscCall(PetscObjectDereference((PetscObject)container)); 7762 PetscFunctionReturn(PETSC_SUCCESS); 7763 } 7764 7765 /*@ 7766 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7767 7768 Collective 7769 7770 Input Parameters: 7771 + A - the matrix 7772 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7773 7774 Output Parameter: 7775 . C - matrix with inverted block diagonal of `A` 7776 7777 Level: advanced 7778 7779 Note: 7780 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7781 7782 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7783 @*/ 7784 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7785 { 7786 PetscContainer container; 7787 EnvelopeData *edata; 7788 PetscObjectState nonzerostate; 7789 7790 PetscFunctionBegin; 7791 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7792 if (!container) { 7793 PetscCall(MatComputeVariableBlockEnvelope(A)); 7794 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7795 } 7796 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7797 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7798 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7799 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7800 7801 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7802 *C = edata->C; 7803 7804 for (PetscInt i = 0; i < edata->n; i++) { 7805 Mat D; 7806 PetscScalar *dvalues; 7807 7808 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7809 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7810 PetscCall(MatSeqDenseInvert(D)); 7811 PetscCall(MatDenseGetArray(D, &dvalues)); 7812 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7813 PetscCall(MatDestroy(&D)); 7814 } 7815 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7816 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7817 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7818 PetscFunctionReturn(PETSC_SUCCESS); 7819 } 7820 7821 /*@ 7822 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7823 7824 Not Collective 7825 7826 Input Parameters: 7827 + mat - the matrix 7828 . nblocks - the number of blocks on this process, each block can only exist on a single process 7829 - bsizes - the block sizes 7830 7831 Level: intermediate 7832 7833 Notes: 7834 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7835 7836 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. 7837 7838 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7839 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7840 @*/ 7841 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7842 { 7843 PetscInt ncnt = 0, nlocal; 7844 7845 PetscFunctionBegin; 7846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7847 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7848 PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal); 7849 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7850 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); 7851 PetscCall(PetscFree(mat->bsizes)); 7852 mat->nblocks = nblocks; 7853 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7854 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7855 PetscFunctionReturn(PETSC_SUCCESS); 7856 } 7857 7858 /*@C 7859 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7860 7861 Not Collective; No Fortran Support 7862 7863 Input Parameter: 7864 . mat - the matrix 7865 7866 Output Parameters: 7867 + nblocks - the number of blocks on this process 7868 - bsizes - the block sizes 7869 7870 Level: intermediate 7871 7872 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7873 @*/ 7874 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7875 { 7876 PetscFunctionBegin; 7877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7878 if (nblocks) *nblocks = mat->nblocks; 7879 if (bsizes) *bsizes = mat->bsizes; 7880 PetscFunctionReturn(PETSC_SUCCESS); 7881 } 7882 7883 /*@ 7884 MatSetBlockSizes - Sets the matrix block row and column sizes. 7885 7886 Logically Collective 7887 7888 Input Parameters: 7889 + mat - the matrix 7890 . rbs - row block size 7891 - cbs - column block size 7892 7893 Level: intermediate 7894 7895 Notes: 7896 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7897 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7898 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7899 7900 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7901 are compatible with the matrix local sizes. 7902 7903 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7904 7905 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7906 @*/ 7907 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7908 { 7909 PetscFunctionBegin; 7910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7911 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7912 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7913 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7914 if (mat->rmap->refcnt) { 7915 ISLocalToGlobalMapping l2g = NULL; 7916 PetscLayout nmap = NULL; 7917 7918 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7919 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7920 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7921 mat->rmap = nmap; 7922 mat->rmap->mapping = l2g; 7923 } 7924 if (mat->cmap->refcnt) { 7925 ISLocalToGlobalMapping l2g = NULL; 7926 PetscLayout nmap = NULL; 7927 7928 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7929 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7930 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7931 mat->cmap = nmap; 7932 mat->cmap->mapping = l2g; 7933 } 7934 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7935 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7936 PetscFunctionReturn(PETSC_SUCCESS); 7937 } 7938 7939 /*@ 7940 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7941 7942 Logically Collective 7943 7944 Input Parameters: 7945 + mat - the matrix 7946 . fromRow - matrix from which to copy row block size 7947 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7948 7949 Level: developer 7950 7951 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7952 @*/ 7953 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7954 { 7955 PetscFunctionBegin; 7956 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7957 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7958 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7959 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7960 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7961 PetscFunctionReturn(PETSC_SUCCESS); 7962 } 7963 7964 /*@ 7965 MatResidual - Default routine to calculate the residual r = b - Ax 7966 7967 Collective 7968 7969 Input Parameters: 7970 + mat - the matrix 7971 . b - the right-hand-side 7972 - x - the approximate solution 7973 7974 Output Parameter: 7975 . r - location to store the residual 7976 7977 Level: developer 7978 7979 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7980 @*/ 7981 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7982 { 7983 PetscFunctionBegin; 7984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7985 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7986 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7987 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7988 PetscValidType(mat, 1); 7989 MatCheckPreallocated(mat, 1); 7990 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7991 if (!mat->ops->residual) { 7992 PetscCall(MatMult(mat, x, r)); 7993 PetscCall(VecAYPX(r, -1.0, b)); 7994 } else { 7995 PetscUseTypeMethod(mat, residual, b, x, r); 7996 } 7997 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7998 PetscFunctionReturn(PETSC_SUCCESS); 7999 } 8000 8001 /*MC 8002 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8003 8004 Synopsis: 8005 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8006 8007 Not Collective 8008 8009 Input Parameters: 8010 + A - the matrix 8011 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8012 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8013 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8014 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8015 always used. 8016 8017 Output Parameters: 8018 + n - number of local rows in the (possibly compressed) matrix 8019 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8020 . ja - the column indices 8021 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8022 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8023 8024 Level: developer 8025 8026 Note: 8027 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8028 8029 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8030 M*/ 8031 8032 /*MC 8033 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8034 8035 Synopsis: 8036 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8037 8038 Not Collective 8039 8040 Input Parameters: 8041 + A - the matrix 8042 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8043 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8044 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8045 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8046 always used. 8047 . n - number of local rows in the (possibly compressed) matrix 8048 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8049 . ja - the column indices 8050 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8051 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8052 8053 Level: developer 8054 8055 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8056 M*/ 8057 8058 /*@C 8059 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8060 8061 Collective 8062 8063 Input Parameters: 8064 + mat - the matrix 8065 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8066 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8067 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8068 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8069 always used. 8070 8071 Output Parameters: 8072 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8073 . 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 8074 . ja - the column indices, use `NULL` if not needed 8075 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8076 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8077 8078 Level: developer 8079 8080 Notes: 8081 You CANNOT change any of the ia[] or ja[] values. 8082 8083 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8084 8085 Fortran Notes: 8086 Use 8087 .vb 8088 PetscInt, pointer :: ia(:),ja(:) 8089 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8090 ! Access the ith and jth entries via ia(i) and ja(j) 8091 .ve 8092 8093 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8094 8095 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8096 @*/ 8097 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8098 { 8099 PetscFunctionBegin; 8100 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8101 PetscValidType(mat, 1); 8102 if (n) PetscAssertPointer(n, 5); 8103 if (ia) PetscAssertPointer(ia, 6); 8104 if (ja) PetscAssertPointer(ja, 7); 8105 if (done) PetscAssertPointer(done, 8); 8106 MatCheckPreallocated(mat, 1); 8107 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8108 else { 8109 if (done) *done = PETSC_TRUE; 8110 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8111 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8112 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8113 } 8114 PetscFunctionReturn(PETSC_SUCCESS); 8115 } 8116 8117 /*@C 8118 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8119 8120 Collective 8121 8122 Input Parameters: 8123 + mat - the matrix 8124 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8125 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8126 symmetrized 8127 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8128 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8129 always used. 8130 . n - number of columns in the (possibly compressed) matrix 8131 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8132 - ja - the row indices 8133 8134 Output Parameter: 8135 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8136 8137 Level: developer 8138 8139 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8140 @*/ 8141 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8142 { 8143 PetscFunctionBegin; 8144 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8145 PetscValidType(mat, 1); 8146 PetscAssertPointer(n, 5); 8147 if (ia) PetscAssertPointer(ia, 6); 8148 if (ja) PetscAssertPointer(ja, 7); 8149 PetscAssertPointer(done, 8); 8150 MatCheckPreallocated(mat, 1); 8151 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8152 else { 8153 *done = PETSC_TRUE; 8154 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8155 } 8156 PetscFunctionReturn(PETSC_SUCCESS); 8157 } 8158 8159 /*@C 8160 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8161 8162 Collective 8163 8164 Input Parameters: 8165 + mat - the matrix 8166 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8167 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8168 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8169 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8170 always used. 8171 . n - size of (possibly compressed) matrix 8172 . ia - the row pointers 8173 - ja - the column indices 8174 8175 Output Parameter: 8176 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8177 8178 Level: developer 8179 8180 Note: 8181 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8182 us of the array after it has been restored. If you pass `NULL`, it will 8183 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8184 8185 Fortran Note: 8186 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8187 8188 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8189 @*/ 8190 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8191 { 8192 PetscFunctionBegin; 8193 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8194 PetscValidType(mat, 1); 8195 if (ia) PetscAssertPointer(ia, 6); 8196 if (ja) PetscAssertPointer(ja, 7); 8197 if (done) PetscAssertPointer(done, 8); 8198 MatCheckPreallocated(mat, 1); 8199 8200 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8201 else { 8202 if (done) *done = PETSC_TRUE; 8203 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8204 if (n) *n = 0; 8205 if (ia) *ia = NULL; 8206 if (ja) *ja = NULL; 8207 } 8208 PetscFunctionReturn(PETSC_SUCCESS); 8209 } 8210 8211 /*@C 8212 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8213 8214 Collective 8215 8216 Input Parameters: 8217 + mat - the matrix 8218 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8219 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8220 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8221 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8222 always used. 8223 8224 Output Parameters: 8225 + n - size of (possibly compressed) matrix 8226 . ia - the column pointers 8227 . ja - the row indices 8228 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8229 8230 Level: developer 8231 8232 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8233 @*/ 8234 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8235 { 8236 PetscFunctionBegin; 8237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8238 PetscValidType(mat, 1); 8239 if (ia) PetscAssertPointer(ia, 6); 8240 if (ja) PetscAssertPointer(ja, 7); 8241 PetscAssertPointer(done, 8); 8242 MatCheckPreallocated(mat, 1); 8243 8244 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8245 else { 8246 *done = PETSC_TRUE; 8247 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8248 if (n) *n = 0; 8249 if (ia) *ia = NULL; 8250 if (ja) *ja = NULL; 8251 } 8252 PetscFunctionReturn(PETSC_SUCCESS); 8253 } 8254 8255 /*@ 8256 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8257 `MatGetColumnIJ()`. 8258 8259 Collective 8260 8261 Input Parameters: 8262 + mat - the matrix 8263 . ncolors - maximum color value 8264 . n - number of entries in colorarray 8265 - colorarray - array indicating color for each column 8266 8267 Output Parameter: 8268 . iscoloring - coloring generated using colorarray information 8269 8270 Level: developer 8271 8272 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8273 @*/ 8274 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8275 { 8276 PetscFunctionBegin; 8277 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8278 PetscValidType(mat, 1); 8279 PetscAssertPointer(colorarray, 4); 8280 PetscAssertPointer(iscoloring, 5); 8281 MatCheckPreallocated(mat, 1); 8282 8283 if (!mat->ops->coloringpatch) { 8284 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8285 } else { 8286 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8287 } 8288 PetscFunctionReturn(PETSC_SUCCESS); 8289 } 8290 8291 /*@ 8292 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8293 8294 Logically Collective 8295 8296 Input Parameter: 8297 . mat - the factored matrix to be reset 8298 8299 Level: developer 8300 8301 Notes: 8302 This routine should be used only with factored matrices formed by in-place 8303 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8304 format). This option can save memory, for example, when solving nonlinear 8305 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8306 ILU(0) preconditioner. 8307 8308 One can specify in-place ILU(0) factorization by calling 8309 .vb 8310 PCType(pc,PCILU); 8311 PCFactorSeUseInPlace(pc); 8312 .ve 8313 or by using the options -pc_type ilu -pc_factor_in_place 8314 8315 In-place factorization ILU(0) can also be used as a local 8316 solver for the blocks within the block Jacobi or additive Schwarz 8317 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8318 for details on setting local solver options. 8319 8320 Most users should employ the `KSP` interface for linear solvers 8321 instead of working directly with matrix algebra routines such as this. 8322 See, e.g., `KSPCreate()`. 8323 8324 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8325 @*/ 8326 PetscErrorCode MatSetUnfactored(Mat mat) 8327 { 8328 PetscFunctionBegin; 8329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8330 PetscValidType(mat, 1); 8331 MatCheckPreallocated(mat, 1); 8332 mat->factortype = MAT_FACTOR_NONE; 8333 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8334 PetscUseTypeMethod(mat, setunfactored); 8335 PetscFunctionReturn(PETSC_SUCCESS); 8336 } 8337 8338 /*MC 8339 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8340 8341 Synopsis: 8342 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8343 8344 Not Collective 8345 8346 Input Parameter: 8347 . x - matrix 8348 8349 Output Parameters: 8350 + xx_v - the Fortran pointer to the array 8351 - ierr - error code 8352 8353 Example of Usage: 8354 .vb 8355 PetscScalar, pointer xx_v(:,:) 8356 .... 8357 call MatDenseGetArrayF90(x,xx_v,ierr) 8358 a = xx_v(3) 8359 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8360 .ve 8361 8362 Level: advanced 8363 8364 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8365 M*/ 8366 8367 /*MC 8368 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8369 accessed with `MatDenseGetArrayF90()`. 8370 8371 Synopsis: 8372 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8373 8374 Not Collective 8375 8376 Input Parameters: 8377 + x - matrix 8378 - xx_v - the Fortran90 pointer to the array 8379 8380 Output Parameter: 8381 . ierr - error code 8382 8383 Example of Usage: 8384 .vb 8385 PetscScalar, pointer xx_v(:,:) 8386 .... 8387 call MatDenseGetArrayF90(x,xx_v,ierr) 8388 a = xx_v(3) 8389 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8390 .ve 8391 8392 Level: advanced 8393 8394 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8395 M*/ 8396 8397 /*MC 8398 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8399 8400 Synopsis: 8401 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8402 8403 Not Collective 8404 8405 Input Parameter: 8406 . x - matrix 8407 8408 Output Parameters: 8409 + xx_v - the Fortran pointer to the array 8410 - ierr - error code 8411 8412 Example of Usage: 8413 .vb 8414 PetscScalar, pointer xx_v(:) 8415 .... 8416 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8417 a = xx_v(3) 8418 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8419 .ve 8420 8421 Level: advanced 8422 8423 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8424 M*/ 8425 8426 /*MC 8427 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8428 accessed with `MatSeqAIJGetArrayF90()`. 8429 8430 Synopsis: 8431 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8432 8433 Not Collective 8434 8435 Input Parameters: 8436 + x - matrix 8437 - xx_v - the Fortran90 pointer to the array 8438 8439 Output Parameter: 8440 . ierr - error code 8441 8442 Example of Usage: 8443 .vb 8444 PetscScalar, pointer xx_v(:) 8445 .... 8446 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8447 a = xx_v(3) 8448 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8449 .ve 8450 8451 Level: advanced 8452 8453 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8454 M*/ 8455 8456 /*@ 8457 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8458 as the original matrix. 8459 8460 Collective 8461 8462 Input Parameters: 8463 + mat - the original matrix 8464 . isrow - parallel `IS` containing the rows this processor should obtain 8465 . 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. 8466 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8467 8468 Output Parameter: 8469 . newmat - the new submatrix, of the same type as the original matrix 8470 8471 Level: advanced 8472 8473 Notes: 8474 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8475 8476 Some matrix types place restrictions on the row and column indices, such 8477 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; 8478 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8479 8480 The index sets may not have duplicate entries. 8481 8482 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8483 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8484 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8485 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8486 you are finished using it. 8487 8488 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8489 the input matrix. 8490 8491 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8492 8493 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8494 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8495 8496 Example usage: 8497 Consider the following 8x8 matrix with 34 non-zero values, that is 8498 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8499 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8500 as follows 8501 .vb 8502 1 2 0 | 0 3 0 | 0 4 8503 Proc0 0 5 6 | 7 0 0 | 8 0 8504 9 0 10 | 11 0 0 | 12 0 8505 ------------------------------------- 8506 13 0 14 | 15 16 17 | 0 0 8507 Proc1 0 18 0 | 19 20 21 | 0 0 8508 0 0 0 | 22 23 0 | 24 0 8509 ------------------------------------- 8510 Proc2 25 26 27 | 0 0 28 | 29 0 8511 30 0 0 | 31 32 33 | 0 34 8512 .ve 8513 8514 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8515 8516 .vb 8517 2 0 | 0 3 0 | 0 8518 Proc0 5 6 | 7 0 0 | 8 8519 ------------------------------- 8520 Proc1 18 0 | 19 20 21 | 0 8521 ------------------------------- 8522 Proc2 26 27 | 0 0 28 | 29 8523 0 0 | 31 32 33 | 0 8524 .ve 8525 8526 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8527 @*/ 8528 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8529 { 8530 PetscMPIInt size; 8531 Mat *local; 8532 IS iscoltmp; 8533 PetscBool flg; 8534 8535 PetscFunctionBegin; 8536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8537 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8538 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8539 PetscAssertPointer(newmat, 5); 8540 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8541 PetscValidType(mat, 1); 8542 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8543 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8544 8545 MatCheckPreallocated(mat, 1); 8546 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8547 8548 if (!iscol || isrow == iscol) { 8549 PetscBool stride; 8550 PetscMPIInt grabentirematrix = 0, grab; 8551 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8552 if (stride) { 8553 PetscInt first, step, n, rstart, rend; 8554 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8555 if (step == 1) { 8556 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8557 if (rstart == first) { 8558 PetscCall(ISGetLocalSize(isrow, &n)); 8559 if (n == rend - rstart) grabentirematrix = 1; 8560 } 8561 } 8562 } 8563 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8564 if (grab) { 8565 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8566 if (cll == MAT_INITIAL_MATRIX) { 8567 *newmat = mat; 8568 PetscCall(PetscObjectReference((PetscObject)mat)); 8569 } 8570 PetscFunctionReturn(PETSC_SUCCESS); 8571 } 8572 } 8573 8574 if (!iscol) { 8575 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8576 } else { 8577 iscoltmp = iscol; 8578 } 8579 8580 /* if original matrix is on just one processor then use submatrix generated */ 8581 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8582 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8583 goto setproperties; 8584 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8585 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8586 *newmat = *local; 8587 PetscCall(PetscFree(local)); 8588 goto setproperties; 8589 } else if (!mat->ops->createsubmatrix) { 8590 /* Create a new matrix type that implements the operation using the full matrix */ 8591 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8592 switch (cll) { 8593 case MAT_INITIAL_MATRIX: 8594 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8595 break; 8596 case MAT_REUSE_MATRIX: 8597 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8598 break; 8599 default: 8600 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8601 } 8602 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8603 goto setproperties; 8604 } 8605 8606 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8607 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8608 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8609 8610 setproperties: 8611 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8612 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8613 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8614 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8615 PetscFunctionReturn(PETSC_SUCCESS); 8616 } 8617 8618 /*@ 8619 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8620 8621 Not Collective 8622 8623 Input Parameters: 8624 + A - the matrix we wish to propagate options from 8625 - B - the matrix we wish to propagate options to 8626 8627 Level: beginner 8628 8629 Note: 8630 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8631 8632 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8633 @*/ 8634 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8635 { 8636 PetscFunctionBegin; 8637 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8638 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8639 B->symmetry_eternal = A->symmetry_eternal; 8640 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8641 B->symmetric = A->symmetric; 8642 B->structurally_symmetric = A->structurally_symmetric; 8643 B->spd = A->spd; 8644 B->hermitian = A->hermitian; 8645 PetscFunctionReturn(PETSC_SUCCESS); 8646 } 8647 8648 /*@ 8649 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8650 used during the assembly process to store values that belong to 8651 other processors. 8652 8653 Not Collective 8654 8655 Input Parameters: 8656 + mat - the matrix 8657 . size - the initial size of the stash. 8658 - bsize - the initial size of the block-stash(if used). 8659 8660 Options Database Keys: 8661 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8662 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8663 8664 Level: intermediate 8665 8666 Notes: 8667 The block-stash is used for values set with `MatSetValuesBlocked()` while 8668 the stash is used for values set with `MatSetValues()` 8669 8670 Run with the option -info and look for output of the form 8671 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8672 to determine the appropriate value, MM, to use for size and 8673 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8674 to determine the value, BMM to use for bsize 8675 8676 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8677 @*/ 8678 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8679 { 8680 PetscFunctionBegin; 8681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8682 PetscValidType(mat, 1); 8683 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8684 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8685 PetscFunctionReturn(PETSC_SUCCESS); 8686 } 8687 8688 /*@ 8689 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8690 the matrix 8691 8692 Neighbor-wise Collective 8693 8694 Input Parameters: 8695 + A - the matrix 8696 . x - the vector to be multiplied by the interpolation operator 8697 - y - the vector to be added to the result 8698 8699 Output Parameter: 8700 . w - the resulting vector 8701 8702 Level: intermediate 8703 8704 Notes: 8705 `w` may be the same vector as `y`. 8706 8707 This allows one to use either the restriction or interpolation (its transpose) 8708 matrix to do the interpolation 8709 8710 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8711 @*/ 8712 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8713 { 8714 PetscInt M, N, Ny; 8715 8716 PetscFunctionBegin; 8717 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8718 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8719 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8720 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8721 PetscCall(MatGetSize(A, &M, &N)); 8722 PetscCall(VecGetSize(y, &Ny)); 8723 if (M == Ny) { 8724 PetscCall(MatMultAdd(A, x, y, w)); 8725 } else { 8726 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8727 } 8728 PetscFunctionReturn(PETSC_SUCCESS); 8729 } 8730 8731 /*@ 8732 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8733 the matrix 8734 8735 Neighbor-wise Collective 8736 8737 Input Parameters: 8738 + A - the matrix 8739 - x - the vector to be interpolated 8740 8741 Output Parameter: 8742 . y - the resulting vector 8743 8744 Level: intermediate 8745 8746 Note: 8747 This allows one to use either the restriction or interpolation (its transpose) 8748 matrix to do the interpolation 8749 8750 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8751 @*/ 8752 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8753 { 8754 PetscInt M, N, Ny; 8755 8756 PetscFunctionBegin; 8757 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8758 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8759 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8760 PetscCall(MatGetSize(A, &M, &N)); 8761 PetscCall(VecGetSize(y, &Ny)); 8762 if (M == Ny) { 8763 PetscCall(MatMult(A, x, y)); 8764 } else { 8765 PetscCall(MatMultTranspose(A, x, y)); 8766 } 8767 PetscFunctionReturn(PETSC_SUCCESS); 8768 } 8769 8770 /*@ 8771 MatRestrict - $y = A*x$ or $A^T*x$ 8772 8773 Neighbor-wise Collective 8774 8775 Input Parameters: 8776 + A - the matrix 8777 - x - the vector to be restricted 8778 8779 Output Parameter: 8780 . y - the resulting vector 8781 8782 Level: intermediate 8783 8784 Note: 8785 This allows one to use either the restriction or interpolation (its transpose) 8786 matrix to do the restriction 8787 8788 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8789 @*/ 8790 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8791 { 8792 PetscInt M, N, Nx; 8793 8794 PetscFunctionBegin; 8795 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8796 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8797 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8798 PetscCall(MatGetSize(A, &M, &N)); 8799 PetscCall(VecGetSize(x, &Nx)); 8800 if (M == Nx) { 8801 PetscCall(MatMultTranspose(A, x, y)); 8802 } else { 8803 PetscCall(MatMult(A, x, y)); 8804 } 8805 PetscFunctionReturn(PETSC_SUCCESS); 8806 } 8807 8808 /*@ 8809 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8810 8811 Neighbor-wise Collective 8812 8813 Input Parameters: 8814 + A - the matrix 8815 . x - the input dense matrix to be multiplied 8816 - w - the input dense matrix to be added to the result 8817 8818 Output Parameter: 8819 . y - the output dense matrix 8820 8821 Level: intermediate 8822 8823 Note: 8824 This allows one to use either the restriction or interpolation (its transpose) 8825 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8826 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8827 8828 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8829 @*/ 8830 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8831 { 8832 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8833 PetscBool trans = PETSC_TRUE; 8834 MatReuse reuse = MAT_INITIAL_MATRIX; 8835 8836 PetscFunctionBegin; 8837 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8838 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8839 PetscValidType(x, 2); 8840 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8841 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8842 PetscCall(MatGetSize(A, &M, &N)); 8843 PetscCall(MatGetSize(x, &Mx, &Nx)); 8844 if (N == Mx) trans = PETSC_FALSE; 8845 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); 8846 Mo = trans ? N : M; 8847 if (*y) { 8848 PetscCall(MatGetSize(*y, &My, &Ny)); 8849 if (Mo == My && Nx == Ny) { 8850 reuse = MAT_REUSE_MATRIX; 8851 } else { 8852 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); 8853 PetscCall(MatDestroy(y)); 8854 } 8855 } 8856 8857 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8858 PetscBool flg; 8859 8860 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8861 if (w) { 8862 PetscInt My, Ny, Mw, Nw; 8863 8864 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8865 PetscCall(MatGetSize(*y, &My, &Ny)); 8866 PetscCall(MatGetSize(w, &Mw, &Nw)); 8867 if (!flg || My != Mw || Ny != Nw) w = NULL; 8868 } 8869 if (!w) { 8870 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8871 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8872 PetscCall(PetscObjectDereference((PetscObject)w)); 8873 } else { 8874 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8875 } 8876 } 8877 if (!trans) { 8878 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8879 } else { 8880 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8881 } 8882 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8883 PetscFunctionReturn(PETSC_SUCCESS); 8884 } 8885 8886 /*@ 8887 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8888 8889 Neighbor-wise Collective 8890 8891 Input Parameters: 8892 + A - the matrix 8893 - x - the input dense matrix 8894 8895 Output Parameter: 8896 . y - the output dense matrix 8897 8898 Level: intermediate 8899 8900 Note: 8901 This allows one to use either the restriction or interpolation (its transpose) 8902 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8903 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8904 8905 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8906 @*/ 8907 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8908 { 8909 PetscFunctionBegin; 8910 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8911 PetscFunctionReturn(PETSC_SUCCESS); 8912 } 8913 8914 /*@ 8915 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8916 8917 Neighbor-wise Collective 8918 8919 Input Parameters: 8920 + A - the matrix 8921 - x - the input dense matrix 8922 8923 Output Parameter: 8924 . y - the output dense matrix 8925 8926 Level: intermediate 8927 8928 Note: 8929 This allows one to use either the restriction or interpolation (its transpose) 8930 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8931 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8932 8933 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8934 @*/ 8935 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8936 { 8937 PetscFunctionBegin; 8938 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8939 PetscFunctionReturn(PETSC_SUCCESS); 8940 } 8941 8942 /*@ 8943 MatGetNullSpace - retrieves the null space of a matrix. 8944 8945 Logically Collective 8946 8947 Input Parameters: 8948 + mat - the matrix 8949 - nullsp - the null space object 8950 8951 Level: developer 8952 8953 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8954 @*/ 8955 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8956 { 8957 PetscFunctionBegin; 8958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8959 PetscAssertPointer(nullsp, 2); 8960 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8961 PetscFunctionReturn(PETSC_SUCCESS); 8962 } 8963 8964 /*@C 8965 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8966 8967 Logically Collective 8968 8969 Input Parameters: 8970 + n - the number of matrices 8971 - mat - the array of matrices 8972 8973 Output Parameters: 8974 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space 8975 8976 Level: developer 8977 8978 Note: 8979 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8980 8981 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8982 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8983 @*/ 8984 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8985 { 8986 PetscFunctionBegin; 8987 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8988 PetscAssertPointer(mat, 2); 8989 PetscAssertPointer(nullsp, 3); 8990 8991 PetscCall(PetscCalloc1(3 * n, nullsp)); 8992 for (PetscInt i = 0; i < n; i++) { 8993 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8994 (*nullsp)[i] = mat[i]->nullsp; 8995 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8996 (*nullsp)[n + i] = mat[i]->nearnullsp; 8997 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8998 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8999 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9000 } 9001 PetscFunctionReturn(PETSC_SUCCESS); 9002 } 9003 9004 /*@C 9005 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9006 9007 Logically Collective 9008 9009 Input Parameters: 9010 + n - the number of matrices 9011 . mat - the array of matrices 9012 - nullsp - an array of null spaces, `NULL` if the null space does not exist 9013 9014 Level: developer 9015 9016 Note: 9017 Call `MatGetNullSpaces()` to create `nullsp` 9018 9019 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9020 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9021 @*/ 9022 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9023 { 9024 PetscFunctionBegin; 9025 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9026 PetscAssertPointer(mat, 2); 9027 PetscAssertPointer(nullsp, 3); 9028 PetscAssertPointer(*nullsp, 3); 9029 9030 for (PetscInt i = 0; i < n; i++) { 9031 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9032 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9033 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9034 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9035 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9036 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9037 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9038 } 9039 PetscCall(PetscFree(*nullsp)); 9040 PetscFunctionReturn(PETSC_SUCCESS); 9041 } 9042 9043 /*@ 9044 MatSetNullSpace - attaches a null space to a matrix. 9045 9046 Logically Collective 9047 9048 Input Parameters: 9049 + mat - the matrix 9050 - nullsp - the null space object 9051 9052 Level: advanced 9053 9054 Notes: 9055 This null space is used by the `KSP` linear solvers to solve singular systems. 9056 9057 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` 9058 9059 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 9060 to zero but the linear system will still be solved in a least squares sense. 9061 9062 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9063 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)$. 9064 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 9065 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 9066 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$). 9067 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9068 9069 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9070 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9071 routine also automatically calls `MatSetTransposeNullSpace()`. 9072 9073 The user should call `MatNullSpaceDestroy()`. 9074 9075 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9076 `KSPSetPCSide()` 9077 @*/ 9078 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9079 { 9080 PetscFunctionBegin; 9081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9082 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9083 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9084 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9085 mat->nullsp = nullsp; 9086 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9087 PetscFunctionReturn(PETSC_SUCCESS); 9088 } 9089 9090 /*@ 9091 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9092 9093 Logically Collective 9094 9095 Input Parameters: 9096 + mat - the matrix 9097 - nullsp - the null space object 9098 9099 Level: developer 9100 9101 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9102 @*/ 9103 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9104 { 9105 PetscFunctionBegin; 9106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9107 PetscValidType(mat, 1); 9108 PetscAssertPointer(nullsp, 2); 9109 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9110 PetscFunctionReturn(PETSC_SUCCESS); 9111 } 9112 9113 /*@ 9114 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9115 9116 Logically Collective 9117 9118 Input Parameters: 9119 + mat - the matrix 9120 - nullsp - the null space object 9121 9122 Level: advanced 9123 9124 Notes: 9125 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9126 9127 See `MatSetNullSpace()` 9128 9129 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9130 @*/ 9131 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9132 { 9133 PetscFunctionBegin; 9134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9135 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9136 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9137 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9138 mat->transnullsp = nullsp; 9139 PetscFunctionReturn(PETSC_SUCCESS); 9140 } 9141 9142 /*@ 9143 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9144 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9145 9146 Logically Collective 9147 9148 Input Parameters: 9149 + mat - the matrix 9150 - nullsp - the null space object 9151 9152 Level: advanced 9153 9154 Notes: 9155 Overwrites any previous near null space that may have been attached 9156 9157 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9158 9159 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9160 @*/ 9161 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9162 { 9163 PetscFunctionBegin; 9164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9165 PetscValidType(mat, 1); 9166 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9167 MatCheckPreallocated(mat, 1); 9168 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9169 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9170 mat->nearnullsp = nullsp; 9171 PetscFunctionReturn(PETSC_SUCCESS); 9172 } 9173 9174 /*@ 9175 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9176 9177 Not Collective 9178 9179 Input Parameter: 9180 . mat - the matrix 9181 9182 Output Parameter: 9183 . nullsp - the null space object, `NULL` if not set 9184 9185 Level: advanced 9186 9187 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9188 @*/ 9189 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9190 { 9191 PetscFunctionBegin; 9192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9193 PetscValidType(mat, 1); 9194 PetscAssertPointer(nullsp, 2); 9195 MatCheckPreallocated(mat, 1); 9196 *nullsp = mat->nearnullsp; 9197 PetscFunctionReturn(PETSC_SUCCESS); 9198 } 9199 9200 /*@C 9201 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9202 9203 Collective 9204 9205 Input Parameters: 9206 + mat - the matrix 9207 . row - row/column permutation 9208 - info - information on desired factorization process 9209 9210 Level: developer 9211 9212 Notes: 9213 Probably really in-place only when level of fill is zero, otherwise allocates 9214 new space to store factored matrix and deletes previous memory. 9215 9216 Most users should employ the `KSP` interface for linear solvers 9217 instead of working directly with matrix algebra routines such as this. 9218 See, e.g., `KSPCreate()`. 9219 9220 Developer Note: 9221 The Fortran interface is not autogenerated as the 9222 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9223 9224 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9225 @*/ 9226 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9227 { 9228 PetscFunctionBegin; 9229 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9230 PetscValidType(mat, 1); 9231 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9232 PetscAssertPointer(info, 3); 9233 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9234 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9235 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9236 MatCheckPreallocated(mat, 1); 9237 PetscUseTypeMethod(mat, iccfactor, row, info); 9238 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9239 PetscFunctionReturn(PETSC_SUCCESS); 9240 } 9241 9242 /*@ 9243 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9244 ghosted ones. 9245 9246 Not Collective 9247 9248 Input Parameters: 9249 + mat - the matrix 9250 - diag - the diagonal values, including ghost ones 9251 9252 Level: developer 9253 9254 Notes: 9255 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9256 9257 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9258 9259 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9260 @*/ 9261 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9262 { 9263 PetscMPIInt size; 9264 9265 PetscFunctionBegin; 9266 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9267 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9268 PetscValidType(mat, 1); 9269 9270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9271 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9272 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9273 if (size == 1) { 9274 PetscInt n, m; 9275 PetscCall(VecGetSize(diag, &n)); 9276 PetscCall(MatGetSize(mat, NULL, &m)); 9277 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9278 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9279 } else { 9280 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9281 } 9282 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9283 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9284 PetscFunctionReturn(PETSC_SUCCESS); 9285 } 9286 9287 /*@ 9288 MatGetInertia - Gets the inertia from a factored matrix 9289 9290 Collective 9291 9292 Input Parameter: 9293 . mat - the matrix 9294 9295 Output Parameters: 9296 + nneg - number of negative eigenvalues 9297 . nzero - number of zero eigenvalues 9298 - npos - number of positive eigenvalues 9299 9300 Level: advanced 9301 9302 Note: 9303 Matrix must have been factored by `MatCholeskyFactor()` 9304 9305 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9306 @*/ 9307 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9308 { 9309 PetscFunctionBegin; 9310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9311 PetscValidType(mat, 1); 9312 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9313 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9314 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9315 PetscFunctionReturn(PETSC_SUCCESS); 9316 } 9317 9318 /*@C 9319 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9320 9321 Neighbor-wise Collective 9322 9323 Input Parameters: 9324 + mat - the factored matrix obtained with `MatGetFactor()` 9325 - b - the right-hand-side vectors 9326 9327 Output Parameter: 9328 . x - the result vectors 9329 9330 Level: developer 9331 9332 Note: 9333 The vectors `b` and `x` cannot be the same. I.e., one cannot 9334 call `MatSolves`(A,x,x). 9335 9336 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9337 @*/ 9338 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9339 { 9340 PetscFunctionBegin; 9341 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9342 PetscValidType(mat, 1); 9343 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9344 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9345 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9346 9347 MatCheckPreallocated(mat, 1); 9348 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9349 PetscUseTypeMethod(mat, solves, b, x); 9350 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9351 PetscFunctionReturn(PETSC_SUCCESS); 9352 } 9353 9354 /*@ 9355 MatIsSymmetric - Test whether a matrix is symmetric 9356 9357 Collective 9358 9359 Input Parameters: 9360 + A - the matrix to test 9361 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9362 9363 Output Parameter: 9364 . flg - the result 9365 9366 Level: intermediate 9367 9368 Notes: 9369 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9370 9371 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9372 9373 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9374 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9375 9376 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9377 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9378 @*/ 9379 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9380 { 9381 PetscFunctionBegin; 9382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9383 PetscAssertPointer(flg, 3); 9384 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9385 else { 9386 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9387 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9388 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9389 } 9390 PetscFunctionReturn(PETSC_SUCCESS); 9391 } 9392 9393 /*@ 9394 MatIsHermitian - Test whether a matrix is Hermitian 9395 9396 Collective 9397 9398 Input Parameters: 9399 + A - the matrix to test 9400 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9401 9402 Output Parameter: 9403 . flg - the result 9404 9405 Level: intermediate 9406 9407 Notes: 9408 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9409 9410 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9411 9412 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9413 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9414 9415 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9416 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9417 @*/ 9418 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9419 { 9420 PetscFunctionBegin; 9421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9422 PetscAssertPointer(flg, 3); 9423 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9424 else { 9425 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9426 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9427 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9428 } 9429 PetscFunctionReturn(PETSC_SUCCESS); 9430 } 9431 9432 /*@ 9433 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9434 9435 Not Collective 9436 9437 Input Parameter: 9438 . A - the matrix to check 9439 9440 Output Parameters: 9441 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9442 - flg - the result (only valid if set is `PETSC_TRUE`) 9443 9444 Level: advanced 9445 9446 Notes: 9447 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9448 if you want it explicitly checked 9449 9450 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9451 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9452 9453 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9454 @*/ 9455 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9456 { 9457 PetscFunctionBegin; 9458 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9459 PetscAssertPointer(set, 2); 9460 PetscAssertPointer(flg, 3); 9461 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9462 *set = PETSC_TRUE; 9463 *flg = PetscBool3ToBool(A->symmetric); 9464 } else { 9465 *set = PETSC_FALSE; 9466 } 9467 PetscFunctionReturn(PETSC_SUCCESS); 9468 } 9469 9470 /*@ 9471 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9472 9473 Not Collective 9474 9475 Input Parameter: 9476 . A - the matrix to check 9477 9478 Output Parameters: 9479 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9480 - flg - the result (only valid if set is `PETSC_TRUE`) 9481 9482 Level: advanced 9483 9484 Notes: 9485 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9486 9487 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9488 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9489 9490 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9491 @*/ 9492 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9493 { 9494 PetscFunctionBegin; 9495 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9496 PetscAssertPointer(set, 2); 9497 PetscAssertPointer(flg, 3); 9498 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9499 *set = PETSC_TRUE; 9500 *flg = PetscBool3ToBool(A->spd); 9501 } else { 9502 *set = PETSC_FALSE; 9503 } 9504 PetscFunctionReturn(PETSC_SUCCESS); 9505 } 9506 9507 /*@ 9508 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9509 9510 Not Collective 9511 9512 Input Parameter: 9513 . A - the matrix to check 9514 9515 Output Parameters: 9516 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9517 - flg - the result (only valid if set is `PETSC_TRUE`) 9518 9519 Level: advanced 9520 9521 Notes: 9522 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9523 if you want it explicitly checked 9524 9525 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9526 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9527 9528 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9529 @*/ 9530 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9531 { 9532 PetscFunctionBegin; 9533 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9534 PetscAssertPointer(set, 2); 9535 PetscAssertPointer(flg, 3); 9536 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9537 *set = PETSC_TRUE; 9538 *flg = PetscBool3ToBool(A->hermitian); 9539 } else { 9540 *set = PETSC_FALSE; 9541 } 9542 PetscFunctionReturn(PETSC_SUCCESS); 9543 } 9544 9545 /*@ 9546 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9547 9548 Collective 9549 9550 Input Parameter: 9551 . A - the matrix to test 9552 9553 Output Parameter: 9554 . flg - the result 9555 9556 Level: intermediate 9557 9558 Notes: 9559 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9560 9561 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 9562 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9563 9564 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9565 @*/ 9566 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9567 { 9568 PetscFunctionBegin; 9569 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9570 PetscAssertPointer(flg, 2); 9571 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9572 *flg = PetscBool3ToBool(A->structurally_symmetric); 9573 } else { 9574 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9575 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9576 } 9577 PetscFunctionReturn(PETSC_SUCCESS); 9578 } 9579 9580 /*@ 9581 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9582 9583 Not Collective 9584 9585 Input Parameter: 9586 . A - the matrix to check 9587 9588 Output Parameters: 9589 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9590 - flg - the result (only valid if set is PETSC_TRUE) 9591 9592 Level: advanced 9593 9594 Notes: 9595 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 9596 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9597 9598 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9599 9600 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9601 @*/ 9602 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9603 { 9604 PetscFunctionBegin; 9605 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9606 PetscAssertPointer(set, 2); 9607 PetscAssertPointer(flg, 3); 9608 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9609 *set = PETSC_TRUE; 9610 *flg = PetscBool3ToBool(A->structurally_symmetric); 9611 } else { 9612 *set = PETSC_FALSE; 9613 } 9614 PetscFunctionReturn(PETSC_SUCCESS); 9615 } 9616 9617 /*@ 9618 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9619 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9620 9621 Not Collective 9622 9623 Input Parameter: 9624 . mat - the matrix 9625 9626 Output Parameters: 9627 + nstash - the size of the stash 9628 . reallocs - the number of additional mallocs incurred. 9629 . bnstash - the size of the block stash 9630 - breallocs - the number of additional mallocs incurred.in the block stash 9631 9632 Level: advanced 9633 9634 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9635 @*/ 9636 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9637 { 9638 PetscFunctionBegin; 9639 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9640 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9641 PetscFunctionReturn(PETSC_SUCCESS); 9642 } 9643 9644 /*@C 9645 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9646 parallel layout, `PetscLayout` for rows and columns 9647 9648 Collective 9649 9650 Input Parameter: 9651 . mat - the matrix 9652 9653 Output Parameters: 9654 + right - (optional) vector that the matrix can be multiplied against 9655 - left - (optional) vector that the matrix vector product can be stored in 9656 9657 Level: advanced 9658 9659 Notes: 9660 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()`. 9661 9662 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9663 9664 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9665 @*/ 9666 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9667 { 9668 PetscFunctionBegin; 9669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9670 PetscValidType(mat, 1); 9671 if (mat->ops->getvecs) { 9672 PetscUseTypeMethod(mat, getvecs, right, left); 9673 } else { 9674 if (right) { 9675 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9676 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9677 PetscCall(VecSetType(*right, mat->defaultvectype)); 9678 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9679 if (mat->boundtocpu && mat->bindingpropagates) { 9680 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9681 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9682 } 9683 #endif 9684 } 9685 if (left) { 9686 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9687 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9688 PetscCall(VecSetType(*left, mat->defaultvectype)); 9689 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9690 if (mat->boundtocpu && mat->bindingpropagates) { 9691 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9692 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9693 } 9694 #endif 9695 } 9696 } 9697 PetscFunctionReturn(PETSC_SUCCESS); 9698 } 9699 9700 /*@C 9701 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9702 with default values. 9703 9704 Not Collective 9705 9706 Input Parameter: 9707 . info - the `MatFactorInfo` data structure 9708 9709 Level: developer 9710 9711 Notes: 9712 The solvers are generally used through the `KSP` and `PC` objects, for example 9713 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9714 9715 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9716 9717 Developer Note: 9718 The Fortran interface is not autogenerated as the 9719 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9720 9721 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9722 @*/ 9723 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9724 { 9725 PetscFunctionBegin; 9726 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9727 PetscFunctionReturn(PETSC_SUCCESS); 9728 } 9729 9730 /*@ 9731 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9732 9733 Collective 9734 9735 Input Parameters: 9736 + mat - the factored matrix 9737 - is - the index set defining the Schur indices (0-based) 9738 9739 Level: advanced 9740 9741 Notes: 9742 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9743 9744 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9745 9746 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9747 9748 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9749 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9750 @*/ 9751 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9752 { 9753 PetscErrorCode (*f)(Mat, IS); 9754 9755 PetscFunctionBegin; 9756 PetscValidType(mat, 1); 9757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9758 PetscValidType(is, 2); 9759 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9760 PetscCheckSameComm(mat, 1, is, 2); 9761 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9762 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9763 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9764 PetscCall(MatDestroy(&mat->schur)); 9765 PetscCall((*f)(mat, is)); 9766 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9767 PetscFunctionReturn(PETSC_SUCCESS); 9768 } 9769 9770 /*@ 9771 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9772 9773 Logically Collective 9774 9775 Input Parameters: 9776 + F - the factored matrix obtained by calling `MatGetFactor()` 9777 . S - location where to return the Schur complement, can be `NULL` 9778 - status - the status of the Schur complement matrix, can be `NULL` 9779 9780 Level: advanced 9781 9782 Notes: 9783 You must call `MatFactorSetSchurIS()` before calling this routine. 9784 9785 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9786 9787 The routine provides a copy of the Schur matrix stored within the solver data structures. 9788 The caller must destroy the object when it is no longer needed. 9789 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9790 9791 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) 9792 9793 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9794 9795 Developer Note: 9796 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9797 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9798 9799 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9800 @*/ 9801 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9802 { 9803 PetscFunctionBegin; 9804 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9805 if (S) PetscAssertPointer(S, 2); 9806 if (status) PetscAssertPointer(status, 3); 9807 if (S) { 9808 PetscErrorCode (*f)(Mat, Mat *); 9809 9810 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9811 if (f) { 9812 PetscCall((*f)(F, S)); 9813 } else { 9814 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9815 } 9816 } 9817 if (status) *status = F->schur_status; 9818 PetscFunctionReturn(PETSC_SUCCESS); 9819 } 9820 9821 /*@ 9822 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9823 9824 Logically Collective 9825 9826 Input Parameters: 9827 + F - the factored matrix obtained by calling `MatGetFactor()` 9828 . S - location where to return the Schur complement, can be `NULL` 9829 - status - the status of the Schur complement matrix, can be `NULL` 9830 9831 Level: advanced 9832 9833 Notes: 9834 You must call `MatFactorSetSchurIS()` before calling this routine. 9835 9836 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9837 9838 The routine returns a the Schur Complement stored within the data structures of the solver. 9839 9840 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9841 9842 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9843 9844 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9845 9846 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9847 9848 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9849 @*/ 9850 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9851 { 9852 PetscFunctionBegin; 9853 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9854 if (S) { 9855 PetscAssertPointer(S, 2); 9856 *S = F->schur; 9857 } 9858 if (status) { 9859 PetscAssertPointer(status, 3); 9860 *status = F->schur_status; 9861 } 9862 PetscFunctionReturn(PETSC_SUCCESS); 9863 } 9864 9865 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9866 { 9867 Mat S = F->schur; 9868 9869 PetscFunctionBegin; 9870 switch (F->schur_status) { 9871 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9872 case MAT_FACTOR_SCHUR_INVERTED: 9873 if (S) { 9874 S->ops->solve = NULL; 9875 S->ops->matsolve = NULL; 9876 S->ops->solvetranspose = NULL; 9877 S->ops->matsolvetranspose = NULL; 9878 S->ops->solveadd = NULL; 9879 S->ops->solvetransposeadd = NULL; 9880 S->factortype = MAT_FACTOR_NONE; 9881 PetscCall(PetscFree(S->solvertype)); 9882 } 9883 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9884 break; 9885 default: 9886 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9887 } 9888 PetscFunctionReturn(PETSC_SUCCESS); 9889 } 9890 9891 /*@ 9892 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9893 9894 Logically Collective 9895 9896 Input Parameters: 9897 + F - the factored matrix obtained by calling `MatGetFactor()` 9898 . S - location where the Schur complement is stored 9899 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9900 9901 Level: advanced 9902 9903 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9904 @*/ 9905 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9906 { 9907 PetscFunctionBegin; 9908 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9909 if (S) { 9910 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9911 *S = NULL; 9912 } 9913 F->schur_status = status; 9914 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9915 PetscFunctionReturn(PETSC_SUCCESS); 9916 } 9917 9918 /*@ 9919 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9920 9921 Logically Collective 9922 9923 Input Parameters: 9924 + F - the factored matrix obtained by calling `MatGetFactor()` 9925 . rhs - location where the right-hand side of the Schur complement system is stored 9926 - sol - location where the solution of the Schur complement system has to be returned 9927 9928 Level: advanced 9929 9930 Notes: 9931 The sizes of the vectors should match the size of the Schur complement 9932 9933 Must be called after `MatFactorSetSchurIS()` 9934 9935 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9936 @*/ 9937 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9938 { 9939 PetscFunctionBegin; 9940 PetscValidType(F, 1); 9941 PetscValidType(rhs, 2); 9942 PetscValidType(sol, 3); 9943 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9944 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9945 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9946 PetscCheckSameComm(F, 1, rhs, 2); 9947 PetscCheckSameComm(F, 1, sol, 3); 9948 PetscCall(MatFactorFactorizeSchurComplement(F)); 9949 switch (F->schur_status) { 9950 case MAT_FACTOR_SCHUR_FACTORED: 9951 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9952 break; 9953 case MAT_FACTOR_SCHUR_INVERTED: 9954 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9955 break; 9956 default: 9957 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9958 } 9959 PetscFunctionReturn(PETSC_SUCCESS); 9960 } 9961 9962 /*@ 9963 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9964 9965 Logically Collective 9966 9967 Input Parameters: 9968 + F - the factored matrix obtained by calling `MatGetFactor()` 9969 . rhs - location where the right-hand side of the Schur complement system is stored 9970 - sol - location where the solution of the Schur complement system has to be returned 9971 9972 Level: advanced 9973 9974 Notes: 9975 The sizes of the vectors should match the size of the Schur complement 9976 9977 Must be called after `MatFactorSetSchurIS()` 9978 9979 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9980 @*/ 9981 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9982 { 9983 PetscFunctionBegin; 9984 PetscValidType(F, 1); 9985 PetscValidType(rhs, 2); 9986 PetscValidType(sol, 3); 9987 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9988 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9989 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9990 PetscCheckSameComm(F, 1, rhs, 2); 9991 PetscCheckSameComm(F, 1, sol, 3); 9992 PetscCall(MatFactorFactorizeSchurComplement(F)); 9993 switch (F->schur_status) { 9994 case MAT_FACTOR_SCHUR_FACTORED: 9995 PetscCall(MatSolve(F->schur, rhs, sol)); 9996 break; 9997 case MAT_FACTOR_SCHUR_INVERTED: 9998 PetscCall(MatMult(F->schur, rhs, sol)); 9999 break; 10000 default: 10001 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10002 } 10003 PetscFunctionReturn(PETSC_SUCCESS); 10004 } 10005 10006 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10007 #if PetscDefined(HAVE_CUDA) 10008 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10009 #endif 10010 10011 /* Schur status updated in the interface */ 10012 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10013 { 10014 Mat S = F->schur; 10015 10016 PetscFunctionBegin; 10017 if (S) { 10018 PetscMPIInt size; 10019 PetscBool isdense, isdensecuda; 10020 10021 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10022 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10023 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10024 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10025 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10026 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10027 if (isdense) { 10028 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10029 } else if (isdensecuda) { 10030 #if defined(PETSC_HAVE_CUDA) 10031 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10032 #endif 10033 } 10034 // HIP?????????????? 10035 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10036 } 10037 PetscFunctionReturn(PETSC_SUCCESS); 10038 } 10039 10040 /*@ 10041 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10042 10043 Logically Collective 10044 10045 Input Parameter: 10046 . F - the factored matrix obtained by calling `MatGetFactor()` 10047 10048 Level: advanced 10049 10050 Notes: 10051 Must be called after `MatFactorSetSchurIS()`. 10052 10053 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10054 10055 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10056 @*/ 10057 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10058 { 10059 PetscFunctionBegin; 10060 PetscValidType(F, 1); 10061 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10062 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10063 PetscCall(MatFactorFactorizeSchurComplement(F)); 10064 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10065 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10066 PetscFunctionReturn(PETSC_SUCCESS); 10067 } 10068 10069 /*@ 10070 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10071 10072 Logically Collective 10073 10074 Input Parameter: 10075 . F - the factored matrix obtained by calling `MatGetFactor()` 10076 10077 Level: advanced 10078 10079 Note: 10080 Must be called after `MatFactorSetSchurIS()` 10081 10082 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10083 @*/ 10084 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10085 { 10086 MatFactorInfo info; 10087 10088 PetscFunctionBegin; 10089 PetscValidType(F, 1); 10090 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10091 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10092 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10093 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10094 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10095 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10096 } else { 10097 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10098 } 10099 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10100 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10101 PetscFunctionReturn(PETSC_SUCCESS); 10102 } 10103 10104 /*@ 10105 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10106 10107 Neighbor-wise Collective 10108 10109 Input Parameters: 10110 + A - the matrix 10111 . P - the projection matrix 10112 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10113 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 10114 if the result is a dense matrix this is irrelevant 10115 10116 Output Parameter: 10117 . C - the product matrix 10118 10119 Level: intermediate 10120 10121 Notes: 10122 C will be created and must be destroyed by the user with `MatDestroy()`. 10123 10124 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10125 10126 Developer Note: 10127 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10128 10129 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10130 @*/ 10131 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10132 { 10133 PetscFunctionBegin; 10134 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10135 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10136 10137 if (scall == MAT_INITIAL_MATRIX) { 10138 PetscCall(MatProductCreate(A, P, NULL, C)); 10139 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10140 PetscCall(MatProductSetAlgorithm(*C, "default")); 10141 PetscCall(MatProductSetFill(*C, fill)); 10142 10143 (*C)->product->api_user = PETSC_TRUE; 10144 PetscCall(MatProductSetFromOptions(*C)); 10145 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); 10146 PetscCall(MatProductSymbolic(*C)); 10147 } else { /* scall == MAT_REUSE_MATRIX */ 10148 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10149 } 10150 10151 PetscCall(MatProductNumeric(*C)); 10152 (*C)->symmetric = A->symmetric; 10153 (*C)->spd = A->spd; 10154 PetscFunctionReturn(PETSC_SUCCESS); 10155 } 10156 10157 /*@ 10158 MatRARt - Creates the matrix product $C = R * A * R^T$ 10159 10160 Neighbor-wise Collective 10161 10162 Input Parameters: 10163 + A - the matrix 10164 . R - the projection matrix 10165 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10166 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 10167 if the result is a dense matrix this is irrelevant 10168 10169 Output Parameter: 10170 . C - the product matrix 10171 10172 Level: intermediate 10173 10174 Notes: 10175 C will be created and must be destroyed by the user with `MatDestroy()`. 10176 10177 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10178 10179 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10180 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10181 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 10182 We recommend using MatPtAP(). 10183 10184 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10185 @*/ 10186 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10187 { 10188 PetscFunctionBegin; 10189 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10190 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10191 10192 if (scall == MAT_INITIAL_MATRIX) { 10193 PetscCall(MatProductCreate(A, R, NULL, C)); 10194 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10195 PetscCall(MatProductSetAlgorithm(*C, "default")); 10196 PetscCall(MatProductSetFill(*C, fill)); 10197 10198 (*C)->product->api_user = PETSC_TRUE; 10199 PetscCall(MatProductSetFromOptions(*C)); 10200 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); 10201 PetscCall(MatProductSymbolic(*C)); 10202 } else { /* scall == MAT_REUSE_MATRIX */ 10203 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10204 } 10205 10206 PetscCall(MatProductNumeric(*C)); 10207 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10208 PetscFunctionReturn(PETSC_SUCCESS); 10209 } 10210 10211 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10212 { 10213 PetscBool flg = PETSC_TRUE; 10214 10215 PetscFunctionBegin; 10216 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10217 if (scall == MAT_INITIAL_MATRIX) { 10218 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10219 PetscCall(MatProductCreate(A, B, NULL, C)); 10220 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10221 PetscCall(MatProductSetFill(*C, fill)); 10222 } else { /* scall == MAT_REUSE_MATRIX */ 10223 Mat_Product *product = (*C)->product; 10224 10225 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10226 if (flg && product && product->type != ptype) { 10227 PetscCall(MatProductClear(*C)); 10228 product = NULL; 10229 } 10230 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10231 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10232 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10233 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10234 product = (*C)->product; 10235 product->fill = fill; 10236 product->clear = PETSC_TRUE; 10237 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10238 flg = PETSC_FALSE; 10239 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10240 } 10241 } 10242 if (flg) { 10243 (*C)->product->api_user = PETSC_TRUE; 10244 PetscCall(MatProductSetType(*C, ptype)); 10245 PetscCall(MatProductSetFromOptions(*C)); 10246 PetscCall(MatProductSymbolic(*C)); 10247 } 10248 PetscCall(MatProductNumeric(*C)); 10249 PetscFunctionReturn(PETSC_SUCCESS); 10250 } 10251 10252 /*@ 10253 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10254 10255 Neighbor-wise Collective 10256 10257 Input Parameters: 10258 + A - the left matrix 10259 . B - the right matrix 10260 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10261 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10262 if the result is a dense matrix this is irrelevant 10263 10264 Output Parameter: 10265 . C - the product matrix 10266 10267 Notes: 10268 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10269 10270 `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 10271 call to this function with `MAT_INITIAL_MATRIX`. 10272 10273 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10274 10275 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`, 10276 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10277 10278 Example of Usage: 10279 .vb 10280 MatProductCreate(A,B,NULL,&C); 10281 MatProductSetType(C,MATPRODUCT_AB); 10282 MatProductSymbolic(C); 10283 MatProductNumeric(C); // compute C=A * B 10284 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10285 MatProductNumeric(C); 10286 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10287 MatProductNumeric(C); 10288 .ve 10289 10290 Level: intermediate 10291 10292 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10293 @*/ 10294 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10295 { 10296 PetscFunctionBegin; 10297 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10298 PetscFunctionReturn(PETSC_SUCCESS); 10299 } 10300 10301 /*@ 10302 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10303 10304 Neighbor-wise Collective 10305 10306 Input Parameters: 10307 + A - the left matrix 10308 . B - the right matrix 10309 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10310 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10311 10312 Output Parameter: 10313 . C - the product matrix 10314 10315 Options Database Key: 10316 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10317 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10318 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10319 10320 Level: intermediate 10321 10322 Notes: 10323 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10324 10325 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10326 10327 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10328 actually needed. 10329 10330 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10331 and for pairs of `MATMPIDENSE` matrices. 10332 10333 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10334 10335 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10336 @*/ 10337 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10338 { 10339 PetscFunctionBegin; 10340 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10341 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10342 PetscFunctionReturn(PETSC_SUCCESS); 10343 } 10344 10345 /*@ 10346 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10347 10348 Neighbor-wise Collective 10349 10350 Input Parameters: 10351 + A - the left matrix 10352 . B - the right matrix 10353 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10354 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10355 10356 Output Parameter: 10357 . C - the product matrix 10358 10359 Level: intermediate 10360 10361 Notes: 10362 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10363 10364 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10365 10366 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10367 10368 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10369 actually needed. 10370 10371 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10372 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10373 10374 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10375 @*/ 10376 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10377 { 10378 PetscFunctionBegin; 10379 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10380 PetscFunctionReturn(PETSC_SUCCESS); 10381 } 10382 10383 /*@ 10384 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10385 10386 Neighbor-wise Collective 10387 10388 Input Parameters: 10389 + A - the left matrix 10390 . B - the middle matrix 10391 . C - the right matrix 10392 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10393 - 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 10394 if the result is a dense matrix this is irrelevant 10395 10396 Output Parameter: 10397 . D - the product matrix 10398 10399 Level: intermediate 10400 10401 Notes: 10402 Unless `scall` is `MAT_REUSE_MATRIX` D will be created. 10403 10404 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10405 10406 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10407 10408 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10409 actually needed. 10410 10411 If you have many matrices with the same non-zero structure to multiply, you 10412 should use `MAT_REUSE_MATRIX` in all calls but the first 10413 10414 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10415 @*/ 10416 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10417 { 10418 PetscFunctionBegin; 10419 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10420 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10421 10422 if (scall == MAT_INITIAL_MATRIX) { 10423 PetscCall(MatProductCreate(A, B, C, D)); 10424 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10425 PetscCall(MatProductSetAlgorithm(*D, "default")); 10426 PetscCall(MatProductSetFill(*D, fill)); 10427 10428 (*D)->product->api_user = PETSC_TRUE; 10429 PetscCall(MatProductSetFromOptions(*D)); 10430 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, 10431 ((PetscObject)C)->type_name); 10432 PetscCall(MatProductSymbolic(*D)); 10433 } else { /* user may change input matrices when REUSE */ 10434 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10435 } 10436 PetscCall(MatProductNumeric(*D)); 10437 PetscFunctionReturn(PETSC_SUCCESS); 10438 } 10439 10440 /*@ 10441 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10442 10443 Collective 10444 10445 Input Parameters: 10446 + mat - the matrix 10447 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10448 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10449 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10450 10451 Output Parameter: 10452 . matredundant - redundant matrix 10453 10454 Level: advanced 10455 10456 Notes: 10457 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10458 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10459 10460 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10461 calling it. 10462 10463 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10464 10465 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10466 @*/ 10467 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10468 { 10469 MPI_Comm comm; 10470 PetscMPIInt size; 10471 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10472 Mat_Redundant *redund = NULL; 10473 PetscSubcomm psubcomm = NULL; 10474 MPI_Comm subcomm_in = subcomm; 10475 Mat *matseq; 10476 IS isrow, iscol; 10477 PetscBool newsubcomm = PETSC_FALSE; 10478 10479 PetscFunctionBegin; 10480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10481 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10482 PetscAssertPointer(*matredundant, 5); 10483 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10484 } 10485 10486 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10487 if (size == 1 || nsubcomm == 1) { 10488 if (reuse == MAT_INITIAL_MATRIX) { 10489 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10490 } else { 10491 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"); 10492 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10493 } 10494 PetscFunctionReturn(PETSC_SUCCESS); 10495 } 10496 10497 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10498 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10499 MatCheckPreallocated(mat, 1); 10500 10501 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10502 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10503 /* create psubcomm, then get subcomm */ 10504 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10505 PetscCallMPI(MPI_Comm_size(comm, &size)); 10506 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10507 10508 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10509 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10510 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10511 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10512 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10513 newsubcomm = PETSC_TRUE; 10514 PetscCall(PetscSubcommDestroy(&psubcomm)); 10515 } 10516 10517 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10518 if (reuse == MAT_INITIAL_MATRIX) { 10519 mloc_sub = PETSC_DECIDE; 10520 nloc_sub = PETSC_DECIDE; 10521 if (bs < 1) { 10522 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10523 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10524 } else { 10525 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10526 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10527 } 10528 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10529 rstart = rend - mloc_sub; 10530 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10531 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10532 PetscCall(ISSetIdentity(iscol)); 10533 } else { /* reuse == MAT_REUSE_MATRIX */ 10534 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"); 10535 /* retrieve subcomm */ 10536 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10537 redund = (*matredundant)->redundant; 10538 isrow = redund->isrow; 10539 iscol = redund->iscol; 10540 matseq = redund->matseq; 10541 } 10542 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10543 10544 /* get matredundant over subcomm */ 10545 if (reuse == MAT_INITIAL_MATRIX) { 10546 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10547 10548 /* create a supporting struct and attach it to C for reuse */ 10549 PetscCall(PetscNew(&redund)); 10550 (*matredundant)->redundant = redund; 10551 redund->isrow = isrow; 10552 redund->iscol = iscol; 10553 redund->matseq = matseq; 10554 if (newsubcomm) { 10555 redund->subcomm = subcomm; 10556 } else { 10557 redund->subcomm = MPI_COMM_NULL; 10558 } 10559 } else { 10560 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10561 } 10562 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10563 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10564 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10565 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10566 } 10567 #endif 10568 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10569 PetscFunctionReturn(PETSC_SUCCESS); 10570 } 10571 10572 /*@C 10573 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10574 a given `Mat`. Each submatrix can span multiple procs. 10575 10576 Collective 10577 10578 Input Parameters: 10579 + mat - the matrix 10580 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10581 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10582 10583 Output Parameter: 10584 . subMat - parallel sub-matrices each spanning a given `subcomm` 10585 10586 Level: advanced 10587 10588 Notes: 10589 The submatrix partition across processors is dictated by `subComm` a 10590 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10591 is not restricted to be grouped with consecutive original MPI processes. 10592 10593 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10594 map directly to the layout of the original matrix [wrt the local 10595 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10596 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10597 the `subMat`. However the offDiagMat looses some columns - and this is 10598 reconstructed with `MatSetValues()` 10599 10600 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10601 10602 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10603 @*/ 10604 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10605 { 10606 PetscMPIInt commsize, subCommSize; 10607 10608 PetscFunctionBegin; 10609 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10610 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10611 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10612 10613 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"); 10614 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10615 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10616 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10617 PetscFunctionReturn(PETSC_SUCCESS); 10618 } 10619 10620 /*@ 10621 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10622 10623 Not Collective 10624 10625 Input Parameters: 10626 + mat - matrix to extract local submatrix from 10627 . isrow - local row indices for submatrix 10628 - iscol - local column indices for submatrix 10629 10630 Output Parameter: 10631 . submat - the submatrix 10632 10633 Level: intermediate 10634 10635 Notes: 10636 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10637 10638 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10639 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10640 10641 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10642 `MatSetValuesBlockedLocal()` will also be implemented. 10643 10644 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10645 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10646 10647 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10648 @*/ 10649 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10650 { 10651 PetscFunctionBegin; 10652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10653 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10654 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10655 PetscCheckSameComm(isrow, 2, iscol, 3); 10656 PetscAssertPointer(submat, 4); 10657 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10658 10659 if (mat->ops->getlocalsubmatrix) { 10660 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10661 } else { 10662 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10663 } 10664 PetscFunctionReturn(PETSC_SUCCESS); 10665 } 10666 10667 /*@ 10668 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10669 10670 Not Collective 10671 10672 Input Parameters: 10673 + mat - matrix to extract local submatrix from 10674 . isrow - local row indices for submatrix 10675 . iscol - local column indices for submatrix 10676 - submat - the submatrix 10677 10678 Level: intermediate 10679 10680 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10681 @*/ 10682 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10683 { 10684 PetscFunctionBegin; 10685 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10686 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10687 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10688 PetscCheckSameComm(isrow, 2, iscol, 3); 10689 PetscAssertPointer(submat, 4); 10690 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10691 10692 if (mat->ops->restorelocalsubmatrix) { 10693 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10694 } else { 10695 PetscCall(MatDestroy(submat)); 10696 } 10697 *submat = NULL; 10698 PetscFunctionReturn(PETSC_SUCCESS); 10699 } 10700 10701 /*@ 10702 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10703 10704 Collective 10705 10706 Input Parameter: 10707 . mat - the matrix 10708 10709 Output Parameter: 10710 . is - if any rows have zero diagonals this contains the list of them 10711 10712 Level: developer 10713 10714 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10715 @*/ 10716 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10717 { 10718 PetscFunctionBegin; 10719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10720 PetscValidType(mat, 1); 10721 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10722 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10723 10724 if (!mat->ops->findzerodiagonals) { 10725 Vec diag; 10726 const PetscScalar *a; 10727 PetscInt *rows; 10728 PetscInt rStart, rEnd, r, nrow = 0; 10729 10730 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10731 PetscCall(MatGetDiagonal(mat, diag)); 10732 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10733 PetscCall(VecGetArrayRead(diag, &a)); 10734 for (r = 0; r < rEnd - rStart; ++r) 10735 if (a[r] == 0.0) ++nrow; 10736 PetscCall(PetscMalloc1(nrow, &rows)); 10737 nrow = 0; 10738 for (r = 0; r < rEnd - rStart; ++r) 10739 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10740 PetscCall(VecRestoreArrayRead(diag, &a)); 10741 PetscCall(VecDestroy(&diag)); 10742 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10743 } else { 10744 PetscUseTypeMethod(mat, findzerodiagonals, is); 10745 } 10746 PetscFunctionReturn(PETSC_SUCCESS); 10747 } 10748 10749 /*@ 10750 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10751 10752 Collective 10753 10754 Input Parameter: 10755 . mat - the matrix 10756 10757 Output Parameter: 10758 . is - contains the list of rows with off block diagonal entries 10759 10760 Level: developer 10761 10762 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10763 @*/ 10764 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10765 { 10766 PetscFunctionBegin; 10767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10768 PetscValidType(mat, 1); 10769 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10770 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10771 10772 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10773 PetscFunctionReturn(PETSC_SUCCESS); 10774 } 10775 10776 /*@C 10777 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10778 10779 Collective; No Fortran Support 10780 10781 Input Parameter: 10782 . mat - the matrix 10783 10784 Output Parameter: 10785 . values - the block inverses in column major order (FORTRAN-like) 10786 10787 Level: advanced 10788 10789 Notes: 10790 The size of the blocks is determined by the block size of the matrix. 10791 10792 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10793 10794 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10795 10796 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10797 @*/ 10798 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10799 { 10800 PetscFunctionBegin; 10801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10802 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10803 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10804 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10805 PetscFunctionReturn(PETSC_SUCCESS); 10806 } 10807 10808 /*@ 10809 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10810 10811 Collective; No Fortran Support 10812 10813 Input Parameters: 10814 + mat - the matrix 10815 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10816 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10817 10818 Output Parameter: 10819 . values - the block inverses in column major order (FORTRAN-like) 10820 10821 Level: advanced 10822 10823 Notes: 10824 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10825 10826 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10827 10828 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10829 @*/ 10830 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10831 { 10832 PetscFunctionBegin; 10833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10834 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10835 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10836 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10837 PetscFunctionReturn(PETSC_SUCCESS); 10838 } 10839 10840 /*@ 10841 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10842 10843 Collective 10844 10845 Input Parameters: 10846 + A - the matrix 10847 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10848 10849 Level: advanced 10850 10851 Note: 10852 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10853 10854 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10855 @*/ 10856 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10857 { 10858 const PetscScalar *vals; 10859 PetscInt *dnnz; 10860 PetscInt m, rstart, rend, bs, i, j; 10861 10862 PetscFunctionBegin; 10863 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10864 PetscCall(MatGetBlockSize(A, &bs)); 10865 PetscCall(MatGetLocalSize(A, &m, NULL)); 10866 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10867 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10868 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10869 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10870 PetscCall(PetscFree(dnnz)); 10871 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10872 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10873 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10874 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10875 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10876 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10877 PetscFunctionReturn(PETSC_SUCCESS); 10878 } 10879 10880 /*@C 10881 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10882 via `MatTransposeColoringCreate()`. 10883 10884 Collective 10885 10886 Input Parameter: 10887 . c - coloring context 10888 10889 Level: intermediate 10890 10891 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10892 @*/ 10893 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10894 { 10895 MatTransposeColoring matcolor = *c; 10896 10897 PetscFunctionBegin; 10898 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10899 if (--((PetscObject)matcolor)->refct > 0) { 10900 matcolor = NULL; 10901 PetscFunctionReturn(PETSC_SUCCESS); 10902 } 10903 10904 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10905 PetscCall(PetscFree(matcolor->rows)); 10906 PetscCall(PetscFree(matcolor->den2sp)); 10907 PetscCall(PetscFree(matcolor->colorforcol)); 10908 PetscCall(PetscFree(matcolor->columns)); 10909 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10910 PetscCall(PetscHeaderDestroy(c)); 10911 PetscFunctionReturn(PETSC_SUCCESS); 10912 } 10913 10914 /*@ 10915 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10916 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10917 `MatTransposeColoring` to sparse `B`. 10918 10919 Collective 10920 10921 Input Parameters: 10922 + coloring - coloring context created with `MatTransposeColoringCreate()` 10923 - B - sparse matrix 10924 10925 Output Parameter: 10926 . Btdense - dense matrix $B^T$ 10927 10928 Level: developer 10929 10930 Note: 10931 These are used internally for some implementations of `MatRARt()` 10932 10933 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10934 @*/ 10935 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10936 { 10937 PetscFunctionBegin; 10938 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10939 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10940 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10941 10942 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10943 PetscFunctionReturn(PETSC_SUCCESS); 10944 } 10945 10946 /*@ 10947 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10948 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10949 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10950 $C_{sp}$ from $C_{den}$. 10951 10952 Collective 10953 10954 Input Parameters: 10955 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10956 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10957 10958 Output Parameter: 10959 . Csp - sparse matrix 10960 10961 Level: developer 10962 10963 Note: 10964 These are used internally for some implementations of `MatRARt()` 10965 10966 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10967 @*/ 10968 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10969 { 10970 PetscFunctionBegin; 10971 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10972 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10973 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10974 10975 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10976 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10977 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10978 PetscFunctionReturn(PETSC_SUCCESS); 10979 } 10980 10981 /*@ 10982 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10983 10984 Collective 10985 10986 Input Parameters: 10987 + mat - the matrix product C 10988 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10989 10990 Output Parameter: 10991 . color - the new coloring context 10992 10993 Level: intermediate 10994 10995 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10996 `MatTransColoringApplyDenToSp()` 10997 @*/ 10998 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10999 { 11000 MatTransposeColoring c; 11001 MPI_Comm comm; 11002 11003 PetscFunctionBegin; 11004 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11005 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11006 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11007 11008 c->ctype = iscoloring->ctype; 11009 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11010 11011 *color = c; 11012 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11013 PetscFunctionReturn(PETSC_SUCCESS); 11014 } 11015 11016 /*@ 11017 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11018 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11019 11020 Not Collective 11021 11022 Input Parameter: 11023 . mat - the matrix 11024 11025 Output Parameter: 11026 . state - the current state 11027 11028 Level: intermediate 11029 11030 Notes: 11031 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11032 different matrices 11033 11034 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11035 11036 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11037 11038 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11039 @*/ 11040 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11041 { 11042 PetscFunctionBegin; 11043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11044 *state = mat->nonzerostate; 11045 PetscFunctionReturn(PETSC_SUCCESS); 11046 } 11047 11048 /*@ 11049 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11050 matrices from each processor 11051 11052 Collective 11053 11054 Input Parameters: 11055 + comm - the communicators the parallel matrix will live on 11056 . seqmat - the input sequential matrices 11057 . n - number of local columns (or `PETSC_DECIDE`) 11058 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11059 11060 Output Parameter: 11061 . mpimat - the parallel matrix generated 11062 11063 Level: developer 11064 11065 Note: 11066 The number of columns of the matrix in EACH processor MUST be the same. 11067 11068 .seealso: [](ch_matrices), `Mat` 11069 @*/ 11070 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11071 { 11072 PetscMPIInt size; 11073 11074 PetscFunctionBegin; 11075 PetscCallMPI(MPI_Comm_size(comm, &size)); 11076 if (size == 1) { 11077 if (reuse == MAT_INITIAL_MATRIX) { 11078 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11079 } else { 11080 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11081 } 11082 PetscFunctionReturn(PETSC_SUCCESS); 11083 } 11084 11085 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"); 11086 11087 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11088 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11089 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11090 PetscFunctionReturn(PETSC_SUCCESS); 11091 } 11092 11093 /*@ 11094 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11095 11096 Collective 11097 11098 Input Parameters: 11099 + A - the matrix to create subdomains from 11100 - N - requested number of subdomains 11101 11102 Output Parameters: 11103 + n - number of subdomains resulting on this MPI process 11104 - iss - `IS` list with indices of subdomains on this MPI process 11105 11106 Level: advanced 11107 11108 Note: 11109 The number of subdomains must be smaller than the communicator size 11110 11111 .seealso: [](ch_matrices), `Mat`, `IS` 11112 @*/ 11113 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11114 { 11115 MPI_Comm comm, subcomm; 11116 PetscMPIInt size, rank, color; 11117 PetscInt rstart, rend, k; 11118 11119 PetscFunctionBegin; 11120 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11121 PetscCallMPI(MPI_Comm_size(comm, &size)); 11122 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11123 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); 11124 *n = 1; 11125 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11126 color = rank / k; 11127 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11128 PetscCall(PetscMalloc1(1, iss)); 11129 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11130 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11131 PetscCallMPI(MPI_Comm_free(&subcomm)); 11132 PetscFunctionReturn(PETSC_SUCCESS); 11133 } 11134 11135 /*@ 11136 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11137 11138 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11139 If they are not the same, uses `MatMatMatMult()`. 11140 11141 Once the coarse grid problem is constructed, correct for interpolation operators 11142 that are not of full rank, which can legitimately happen in the case of non-nested 11143 geometric multigrid. 11144 11145 Input Parameters: 11146 + restrct - restriction operator 11147 . dA - fine grid matrix 11148 . interpolate - interpolation operator 11149 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11150 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 11151 11152 Output Parameter: 11153 . A - the Galerkin coarse matrix 11154 11155 Options Database Key: 11156 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11157 11158 Level: developer 11159 11160 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11161 @*/ 11162 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11163 { 11164 IS zerorows; 11165 Vec diag; 11166 11167 PetscFunctionBegin; 11168 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11169 /* Construct the coarse grid matrix */ 11170 if (interpolate == restrct) { 11171 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11172 } else { 11173 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11174 } 11175 11176 /* If the interpolation matrix is not of full rank, A will have zero rows. 11177 This can legitimately happen in the case of non-nested geometric multigrid. 11178 In that event, we set the rows of the matrix to the rows of the identity, 11179 ignoring the equations (as the RHS will also be zero). */ 11180 11181 PetscCall(MatFindZeroRows(*A, &zerorows)); 11182 11183 if (zerorows != NULL) { /* if there are any zero rows */ 11184 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11185 PetscCall(MatGetDiagonal(*A, diag)); 11186 PetscCall(VecISSet(diag, zerorows, 1.0)); 11187 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11188 PetscCall(VecDestroy(&diag)); 11189 PetscCall(ISDestroy(&zerorows)); 11190 } 11191 PetscFunctionReturn(PETSC_SUCCESS); 11192 } 11193 11194 /*@C 11195 MatSetOperation - Allows user to set a matrix operation for any matrix type 11196 11197 Logically Collective 11198 11199 Input Parameters: 11200 + mat - the matrix 11201 . op - the name of the operation 11202 - f - the function that provides the operation 11203 11204 Level: developer 11205 11206 Example Usage: 11207 .vb 11208 extern PetscErrorCode usermult(Mat, Vec, Vec); 11209 11210 PetscCall(MatCreateXXX(comm, ..., &A)); 11211 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11212 .ve 11213 11214 Notes: 11215 See the file `include/petscmat.h` for a complete list of matrix 11216 operations, which all have the form MATOP_<OPERATION>, where 11217 <OPERATION> is the name (in all capital letters) of the 11218 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11219 11220 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11221 sequence as the usual matrix interface routines, since they 11222 are intended to be accessed via the usual matrix interface 11223 routines, e.g., 11224 .vb 11225 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11226 .ve 11227 11228 In particular each function MUST return `PETSC_SUCCESS` on success and 11229 nonzero on failure. 11230 11231 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11232 11233 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11234 @*/ 11235 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11236 { 11237 PetscFunctionBegin; 11238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11239 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11240 (((void (**)(void))mat->ops)[op]) = f; 11241 PetscFunctionReturn(PETSC_SUCCESS); 11242 } 11243 11244 /*@C 11245 MatGetOperation - Gets a matrix operation for any matrix type. 11246 11247 Not Collective 11248 11249 Input Parameters: 11250 + mat - the matrix 11251 - op - the name of the operation 11252 11253 Output Parameter: 11254 . f - the function that provides the operation 11255 11256 Level: developer 11257 11258 Example Usage: 11259 .vb 11260 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11261 11262 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11263 .ve 11264 11265 Notes: 11266 See the file include/petscmat.h for a complete list of matrix 11267 operations, which all have the form MATOP_<OPERATION>, where 11268 <OPERATION> is the name (in all capital letters) of the 11269 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11270 11271 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11272 11273 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11274 @*/ 11275 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11276 { 11277 PetscFunctionBegin; 11278 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11279 *f = (((void (**)(void))mat->ops)[op]); 11280 PetscFunctionReturn(PETSC_SUCCESS); 11281 } 11282 11283 /*@ 11284 MatHasOperation - Determines whether the given matrix supports the particular operation. 11285 11286 Not Collective 11287 11288 Input Parameters: 11289 + mat - the matrix 11290 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11291 11292 Output Parameter: 11293 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11294 11295 Level: advanced 11296 11297 Note: 11298 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11299 11300 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11301 @*/ 11302 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11303 { 11304 PetscFunctionBegin; 11305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11306 PetscAssertPointer(has, 3); 11307 if (mat->ops->hasoperation) { 11308 PetscUseTypeMethod(mat, hasoperation, op, has); 11309 } else { 11310 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11311 else { 11312 *has = PETSC_FALSE; 11313 if (op == MATOP_CREATE_SUBMATRIX) { 11314 PetscMPIInt size; 11315 11316 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11317 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11318 } 11319 } 11320 } 11321 PetscFunctionReturn(PETSC_SUCCESS); 11322 } 11323 11324 /*@ 11325 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11326 11327 Collective 11328 11329 Input Parameter: 11330 . mat - the matrix 11331 11332 Output Parameter: 11333 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11334 11335 Level: beginner 11336 11337 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11338 @*/ 11339 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11340 { 11341 PetscFunctionBegin; 11342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11343 PetscValidType(mat, 1); 11344 PetscAssertPointer(cong, 2); 11345 if (!mat->rmap || !mat->cmap) { 11346 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11347 PetscFunctionReturn(PETSC_SUCCESS); 11348 } 11349 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11350 PetscCall(PetscLayoutSetUp(mat->rmap)); 11351 PetscCall(PetscLayoutSetUp(mat->cmap)); 11352 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11353 if (*cong) mat->congruentlayouts = 1; 11354 else mat->congruentlayouts = 0; 11355 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11356 PetscFunctionReturn(PETSC_SUCCESS); 11357 } 11358 11359 PetscErrorCode MatSetInf(Mat A) 11360 { 11361 PetscFunctionBegin; 11362 PetscUseTypeMethod(A, setinf); 11363 PetscFunctionReturn(PETSC_SUCCESS); 11364 } 11365 11366 /*@ 11367 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 11368 and possibly removes small values from the graph structure. 11369 11370 Collective 11371 11372 Input Parameters: 11373 + A - the matrix 11374 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11375 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11376 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11377 . num_idx - size of 'index' array 11378 - index - array of block indices to use for graph strength of connection weight 11379 11380 Output Parameter: 11381 . graph - the resulting graph 11382 11383 Level: advanced 11384 11385 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11386 @*/ 11387 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11388 { 11389 PetscFunctionBegin; 11390 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11391 PetscValidType(A, 1); 11392 PetscValidLogicalCollectiveBool(A, scale, 3); 11393 PetscAssertPointer(graph, 7); 11394 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11395 PetscFunctionReturn(PETSC_SUCCESS); 11396 } 11397 11398 /*@ 11399 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11400 meaning the same memory is used for the matrix, and no new memory is allocated. 11401 11402 Collective 11403 11404 Input Parameters: 11405 + A - the matrix 11406 - 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 11407 11408 Level: intermediate 11409 11410 Developer Note: 11411 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11412 of the arrays in the data structure are unneeded. 11413 11414 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11415 @*/ 11416 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11417 { 11418 PetscFunctionBegin; 11419 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11420 PetscUseTypeMethod(A, eliminatezeros, keep); 11421 PetscFunctionReturn(PETSC_SUCCESS); 11422 } 11423