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_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 109 110 Logically Collective 111 112 Input Parameter: 113 . mat - the factored matrix 114 115 Output Parameters: 116 + pivot - the pivot value computed 117 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 118 the share the matrix 119 120 Level: advanced 121 122 Notes: 123 This routine does not work for factorizations done with external packages. 124 125 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 126 127 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 128 129 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 130 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 131 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 132 @*/ 133 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 134 { 135 PetscFunctionBegin; 136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 137 PetscAssertPointer(pivot, 2); 138 PetscAssertPointer(row, 3); 139 *pivot = mat->factorerror_zeropivot_value; 140 *row = mat->factorerror_zeropivot_row; 141 PetscFunctionReturn(PETSC_SUCCESS); 142 } 143 144 /*@ 145 MatFactorGetError - gets the error code from a factorization 146 147 Logically Collective 148 149 Input Parameter: 150 . mat - the factored matrix 151 152 Output Parameter: 153 . err - the error code 154 155 Level: advanced 156 157 Note: 158 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 159 160 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 161 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 162 @*/ 163 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 164 { 165 PetscFunctionBegin; 166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 167 PetscAssertPointer(err, 2); 168 *err = mat->factorerrortype; 169 PetscFunctionReturn(PETSC_SUCCESS); 170 } 171 172 /*@ 173 MatFactorClearError - clears the error code in a factorization 174 175 Logically Collective 176 177 Input Parameter: 178 . mat - the factored matrix 179 180 Level: developer 181 182 Note: 183 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 184 185 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 186 `MatGetErrorCode()`, `MatFactorError` 187 @*/ 188 PetscErrorCode MatFactorClearError(Mat mat) 189 { 190 PetscFunctionBegin; 191 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 192 mat->factorerrortype = MAT_FACTOR_NOERROR; 193 mat->factorerror_zeropivot_value = 0.0; 194 mat->factorerror_zeropivot_row = 0; 195 PetscFunctionReturn(PETSC_SUCCESS); 196 } 197 198 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 199 { 200 Vec r, l; 201 const PetscScalar *al; 202 PetscInt i, nz, gnz, N, n, st; 203 204 PetscFunctionBegin; 205 PetscCall(MatCreateVecs(mat, &r, &l)); 206 if (!cols) { /* nonzero rows */ 207 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 208 PetscCall(MatGetSize(mat, &N, NULL)); 209 PetscCall(MatGetLocalSize(mat, &n, NULL)); 210 PetscCall(VecSet(l, 0.0)); 211 PetscCall(VecSetRandom(r, NULL)); 212 PetscCall(MatMult(mat, r, l)); 213 PetscCall(VecGetArrayRead(l, &al)); 214 } else { /* nonzero columns */ 215 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 216 PetscCall(MatGetSize(mat, NULL, &N)); 217 PetscCall(MatGetLocalSize(mat, NULL, &n)); 218 PetscCall(VecSet(r, 0.0)); 219 PetscCall(VecSetRandom(l, NULL)); 220 PetscCall(MatMultTranspose(mat, l, r)); 221 PetscCall(VecGetArrayRead(r, &al)); 222 } 223 if (tol <= 0.0) { 224 for (i = 0, nz = 0; i < n; i++) 225 if (al[i] != 0.0) nz++; 226 } else { 227 for (i = 0, nz = 0; i < n; i++) 228 if (PetscAbsScalar(al[i]) > tol) nz++; 229 } 230 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 231 if (gnz != N) { 232 PetscInt *nzr; 233 PetscCall(PetscMalloc1(nz, &nzr)); 234 if (nz) { 235 if (tol < 0) { 236 for (i = 0, nz = 0; i < n; i++) 237 if (al[i] != 0.0) nzr[nz++] = i + st; 238 } else { 239 for (i = 0, nz = 0; i < n; i++) 240 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 241 } 242 } 243 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 244 } else *nonzero = NULL; 245 if (!cols) { /* nonzero rows */ 246 PetscCall(VecRestoreArrayRead(l, &al)); 247 } else { 248 PetscCall(VecRestoreArrayRead(r, &al)); 249 } 250 PetscCall(VecDestroy(&l)); 251 PetscCall(VecDestroy(&r)); 252 PetscFunctionReturn(PETSC_SUCCESS); 253 } 254 255 /*@ 256 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 257 258 Input Parameter: 259 . mat - the matrix 260 261 Output Parameter: 262 . keptrows - the rows that are not completely zero 263 264 Level: intermediate 265 266 Note: 267 `keptrows` is set to `NULL` if all rows are nonzero. 268 269 Developer Note: 270 If `keptrows` is not `NULL`, it must be sorted. 271 272 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 273 @*/ 274 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 275 { 276 PetscFunctionBegin; 277 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 278 PetscValidType(mat, 1); 279 PetscAssertPointer(keptrows, 2); 280 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 281 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 282 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 283 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 284 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 285 PetscFunctionReturn(PETSC_SUCCESS); 286 } 287 288 /*@ 289 MatFindZeroRows - Locate all rows that are completely zero in the matrix 290 291 Input Parameter: 292 . mat - the matrix 293 294 Output Parameter: 295 . zerorows - the rows that are completely zero 296 297 Level: intermediate 298 299 Note: 300 `zerorows` is set to `NULL` if no rows are zero. 301 302 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 303 @*/ 304 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 305 { 306 IS keptrows; 307 PetscInt m, n; 308 309 PetscFunctionBegin; 310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 311 PetscValidType(mat, 1); 312 PetscAssertPointer(zerorows, 2); 313 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 314 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 315 In keeping with this convention, we set zerorows to NULL if there are no zero 316 rows. */ 317 if (keptrows == NULL) { 318 *zerorows = NULL; 319 } else { 320 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 321 PetscCall(ISComplement(keptrows, m, n, zerorows)); 322 PetscCall(ISDestroy(&keptrows)); 323 } 324 PetscFunctionReturn(PETSC_SUCCESS); 325 } 326 327 /*@ 328 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 329 330 Not Collective 331 332 Input Parameter: 333 . A - the matrix 334 335 Output Parameter: 336 . a - the diagonal part (which is a SEQUENTIAL matrix) 337 338 Level: advanced 339 340 Notes: 341 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 342 343 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 344 345 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 346 @*/ 347 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 348 { 349 PetscFunctionBegin; 350 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 351 PetscValidType(A, 1); 352 PetscAssertPointer(a, 2); 353 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 354 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 355 else { 356 PetscMPIInt size; 357 358 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 359 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 360 *a = A; 361 } 362 PetscFunctionReturn(PETSC_SUCCESS); 363 } 364 365 /*@ 366 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 367 368 Collective 369 370 Input Parameter: 371 . mat - the matrix 372 373 Output Parameter: 374 . trace - the sum of the diagonal entries 375 376 Level: advanced 377 378 .seealso: [](ch_matrices), `Mat` 379 @*/ 380 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 381 { 382 Vec diag; 383 384 PetscFunctionBegin; 385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 386 PetscAssertPointer(trace, 2); 387 PetscCall(MatCreateVecs(mat, &diag, NULL)); 388 PetscCall(MatGetDiagonal(mat, diag)); 389 PetscCall(VecSum(diag, trace)); 390 PetscCall(VecDestroy(&diag)); 391 PetscFunctionReturn(PETSC_SUCCESS); 392 } 393 394 /*@ 395 MatRealPart - Zeros out the imaginary part of the matrix 396 397 Logically Collective 398 399 Input Parameter: 400 . mat - the matrix 401 402 Level: advanced 403 404 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 405 @*/ 406 PetscErrorCode MatRealPart(Mat mat) 407 { 408 PetscFunctionBegin; 409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 410 PetscValidType(mat, 1); 411 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 412 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 413 MatCheckPreallocated(mat, 1); 414 PetscUseTypeMethod(mat, realpart); 415 PetscFunctionReturn(PETSC_SUCCESS); 416 } 417 418 /*@C 419 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 420 421 Collective 422 423 Input Parameter: 424 . mat - the matrix 425 426 Output Parameters: 427 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 428 - ghosts - the global indices of the ghost points 429 430 Level: advanced 431 432 Note: 433 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 434 435 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 436 @*/ 437 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 438 { 439 PetscFunctionBegin; 440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 441 PetscValidType(mat, 1); 442 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 443 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 444 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 445 else { 446 if (nghosts) *nghosts = 0; 447 if (ghosts) *ghosts = NULL; 448 } 449 PetscFunctionReturn(PETSC_SUCCESS); 450 } 451 452 /*@ 453 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 454 455 Logically Collective 456 457 Input Parameter: 458 . mat - the matrix 459 460 Level: advanced 461 462 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 463 @*/ 464 PetscErrorCode MatImaginaryPart(Mat mat) 465 { 466 PetscFunctionBegin; 467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 468 PetscValidType(mat, 1); 469 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 470 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 471 MatCheckPreallocated(mat, 1); 472 PetscUseTypeMethod(mat, imaginarypart); 473 PetscFunctionReturn(PETSC_SUCCESS); 474 } 475 476 /*@ 477 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 478 479 Not Collective 480 481 Input Parameter: 482 . mat - the matrix 483 484 Output Parameters: 485 + missing - is any diagonal entry missing 486 - dd - first diagonal entry that is missing (optional) on this process 487 488 Level: advanced 489 490 Note: 491 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 492 493 .seealso: [](ch_matrices), `Mat` 494 @*/ 495 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 496 { 497 PetscFunctionBegin; 498 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 499 PetscValidType(mat, 1); 500 PetscAssertPointer(missing, 2); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 504 PetscFunctionReturn(PETSC_SUCCESS); 505 } 506 507 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 508 /*@C 509 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 510 for each row that you get to ensure that your application does 511 not bleed memory. 512 513 Not Collective 514 515 Input Parameters: 516 + mat - the matrix 517 - row - the row to get 518 519 Output Parameters: 520 + ncols - if not `NULL`, the number of nonzeros in `row` 521 . cols - if not `NULL`, the column numbers 522 - vals - if not `NULL`, the numerical values 523 524 Level: advanced 525 526 Notes: 527 This routine is provided for people who need to have direct access 528 to the structure of a matrix. We hope that we provide enough 529 high-level matrix routines that few users will need it. 530 531 `MatGetRow()` always returns 0-based column indices, regardless of 532 whether the internal representation is 0-based (default) or 1-based. 533 534 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 535 not wish to extract these quantities. 536 537 The user can only examine the values extracted with `MatGetRow()`; 538 the values CANNOT be altered. To change the matrix entries, one 539 must use `MatSetValues()`. 540 541 You can only have one call to `MatGetRow()` outstanding for a particular 542 matrix at a time, per processor. `MatGetRow()` can only obtain rows 543 associated with the given processor, it cannot get rows from the 544 other processors; for that we suggest using `MatCreateSubMatrices()`, then 545 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 546 is in the global number of rows. 547 548 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 549 550 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 551 552 Fortran Note: 553 The calling sequence is 554 .vb 555 MatGetRow(matrix,row,ncols,cols,values,ierr) 556 Mat matrix (input) 557 PetscInt row (input) 558 PetscInt ncols (output) 559 PetscInt cols(maxcols) (output) 560 PetscScalar values(maxcols) output 561 .ve 562 where maxcols >= maximum nonzeros in any row of the matrix. 563 564 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 565 @*/ 566 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 567 { 568 PetscInt incols; 569 570 PetscFunctionBegin; 571 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 572 PetscValidType(mat, 1); 573 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 574 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 575 MatCheckPreallocated(mat, 1); 576 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); 577 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 578 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 579 if (ncols) *ncols = incols; 580 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 581 PetscFunctionReturn(PETSC_SUCCESS); 582 } 583 584 /*@ 585 MatConjugate - replaces the matrix values with their complex conjugates 586 587 Logically Collective 588 589 Input Parameter: 590 . mat - the matrix 591 592 Level: advanced 593 594 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 595 @*/ 596 PetscErrorCode MatConjugate(Mat mat) 597 { 598 PetscFunctionBegin; 599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 601 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 602 PetscUseTypeMethod(mat, conjugate); 603 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 604 } 605 PetscFunctionReturn(PETSC_SUCCESS); 606 } 607 608 /*@C 609 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 610 611 Not Collective 612 613 Input Parameters: 614 + mat - the matrix 615 . row - the row to get 616 . ncols - the number of nonzeros 617 . cols - the columns of the nonzeros 618 - vals - if nonzero the column values 619 620 Level: advanced 621 622 Notes: 623 This routine should be called after you have finished examining the entries. 624 625 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 626 us of the array after it has been restored. If you pass `NULL`, it will 627 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 628 629 Fortran Note: 630 `MatRestoreRow()` MUST be called after `MatGetRow()` 631 before another call to `MatGetRow()` can be made. 632 633 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 634 @*/ 635 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 636 { 637 PetscFunctionBegin; 638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 639 if (ncols) PetscAssertPointer(ncols, 3); 640 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 641 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 642 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 643 if (ncols) *ncols = 0; 644 if (cols) *cols = NULL; 645 if (vals) *vals = NULL; 646 PetscFunctionReturn(PETSC_SUCCESS); 647 } 648 649 /*@ 650 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 651 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 652 653 Not Collective 654 655 Input Parameter: 656 . mat - the matrix 657 658 Level: advanced 659 660 Note: 661 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. 662 663 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 664 @*/ 665 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 666 { 667 PetscFunctionBegin; 668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 669 PetscValidType(mat, 1); 670 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 671 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 672 MatCheckPreallocated(mat, 1); 673 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 674 PetscUseTypeMethod(mat, getrowuppertriangular); 675 PetscFunctionReturn(PETSC_SUCCESS); 676 } 677 678 /*@ 679 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 680 681 Not Collective 682 683 Input Parameter: 684 . mat - the matrix 685 686 Level: advanced 687 688 Note: 689 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 690 691 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 692 @*/ 693 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 694 { 695 PetscFunctionBegin; 696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 697 PetscValidType(mat, 1); 698 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 699 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 700 MatCheckPreallocated(mat, 1); 701 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 702 PetscUseTypeMethod(mat, restorerowuppertriangular); 703 PetscFunctionReturn(PETSC_SUCCESS); 704 } 705 706 /*@ 707 MatSetOptionsPrefix - Sets the prefix used for searching for all 708 `Mat` options in the database. 709 710 Logically Collective 711 712 Input Parameters: 713 + A - the matrix 714 - prefix - the prefix to prepend to all option names 715 716 Level: advanced 717 718 Notes: 719 A hyphen (-) must NOT be given at the beginning of the prefix name. 720 The first character of all runtime options is AUTOMATICALLY the hyphen. 721 722 This is NOT used for options for the factorization of the matrix. Normally the 723 prefix is automatically passed in from the PC calling the factorization. To set 724 it directly use `MatSetOptionsPrefixFactor()` 725 726 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 727 @*/ 728 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 729 { 730 PetscFunctionBegin; 731 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 732 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 733 PetscFunctionReturn(PETSC_SUCCESS); 734 } 735 736 /*@ 737 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 738 for matrices created with `MatGetFactor()` 739 740 Logically Collective 741 742 Input Parameters: 743 + A - the matrix 744 - prefix - the prefix to prepend to all option names for the factored matrix 745 746 Level: developer 747 748 Notes: 749 A hyphen (-) must NOT be given at the beginning of the prefix name. 750 The first character of all runtime options is AUTOMATICALLY the hyphen. 751 752 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 753 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 754 755 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 756 @*/ 757 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 758 { 759 PetscFunctionBegin; 760 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 761 if (prefix) { 762 PetscAssertPointer(prefix, 2); 763 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 764 if (prefix != A->factorprefix) { 765 PetscCall(PetscFree(A->factorprefix)); 766 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 767 } 768 } else PetscCall(PetscFree(A->factorprefix)); 769 PetscFunctionReturn(PETSC_SUCCESS); 770 } 771 772 /*@ 773 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 774 for matrices created with `MatGetFactor()` 775 776 Logically Collective 777 778 Input Parameters: 779 + A - the matrix 780 - prefix - the prefix to prepend to all option names for the factored matrix 781 782 Level: developer 783 784 Notes: 785 A hyphen (-) must NOT be given at the beginning of the prefix name. 786 The first character of all runtime options is AUTOMATICALLY the hyphen. 787 788 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 789 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 790 791 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 792 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 793 `MatSetOptionsPrefix()` 794 @*/ 795 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 796 { 797 size_t len1, len2, new_len; 798 799 PetscFunctionBegin; 800 PetscValidHeader(A, 1); 801 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 802 if (!A->factorprefix) { 803 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 804 PetscFunctionReturn(PETSC_SUCCESS); 805 } 806 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 807 808 PetscCall(PetscStrlen(A->factorprefix, &len1)); 809 PetscCall(PetscStrlen(prefix, &len2)); 810 new_len = len1 + len2 + 1; 811 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 812 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 813 PetscFunctionReturn(PETSC_SUCCESS); 814 } 815 816 /*@ 817 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 818 matrix options in the database. 819 820 Logically Collective 821 822 Input Parameters: 823 + A - the matrix 824 - prefix - the prefix to prepend to all option names 825 826 Level: advanced 827 828 Note: 829 A hyphen (-) must NOT be given at the beginning of the prefix name. 830 The first character of all runtime options is AUTOMATICALLY the hyphen. 831 832 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 833 @*/ 834 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 835 { 836 PetscFunctionBegin; 837 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 838 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 839 PetscFunctionReturn(PETSC_SUCCESS); 840 } 841 842 /*@ 843 MatGetOptionsPrefix - Gets the prefix used for searching for all 844 matrix options in the database. 845 846 Not Collective 847 848 Input Parameter: 849 . A - the matrix 850 851 Output Parameter: 852 . prefix - pointer to the prefix string used 853 854 Level: advanced 855 856 Fortran Note: 857 The user should pass in a string `prefix` of 858 sufficient length to hold the prefix. 859 860 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 861 @*/ 862 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 863 { 864 PetscFunctionBegin; 865 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 866 PetscAssertPointer(prefix, 2); 867 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 868 PetscFunctionReturn(PETSC_SUCCESS); 869 } 870 871 /*@ 872 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 873 874 Not Collective 875 876 Input Parameter: 877 . A - the matrix 878 879 Output Parameter: 880 . state - the object state 881 882 Level: advanced 883 884 Note: 885 Object state is an integer which gets increased every time 886 the object is changed. By saving and later querying the object state 887 one can determine whether information about the object is still current. 888 889 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 890 891 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 892 @*/ 893 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscAssertPointer(state, 2); 898 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 /*@ 903 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: beginner 911 912 Notes: 913 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 914 915 Users can reset the preallocation to access the original memory. 916 917 Currently only supported for `MATAIJ` matrices. 918 919 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 920 @*/ 921 PetscErrorCode MatResetPreallocation(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 PetscValidType(A, 1); 926 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()"); 927 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 928 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 929 PetscFunctionReturn(PETSC_SUCCESS); 930 } 931 932 /*@ 933 MatSetUp - Sets up the internal matrix data structures for later use. 934 935 Collective 936 937 Input Parameter: 938 . A - the matrix 939 940 Level: intermediate 941 942 Notes: 943 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 944 setting values in the matrix. 945 946 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 947 948 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 949 @*/ 950 PetscErrorCode MatSetUp(Mat A) 951 { 952 PetscFunctionBegin; 953 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 954 if (!((PetscObject)A)->type_name) { 955 PetscMPIInt size; 956 957 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 958 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 959 } 960 if (!A->preallocated) PetscTryTypeMethod(A, setup); 961 PetscCall(PetscLayoutSetUp(A->rmap)); 962 PetscCall(PetscLayoutSetUp(A->cmap)); 963 A->preallocated = PETSC_TRUE; 964 PetscFunctionReturn(PETSC_SUCCESS); 965 } 966 967 #if defined(PETSC_HAVE_SAWS) 968 #include <petscviewersaws.h> 969 #endif 970 971 /* 972 If threadsafety is on extraneous matrices may be printed 973 974 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 975 */ 976 #if !defined(PETSC_HAVE_THREADSAFETY) 977 static PetscInt insidematview = 0; 978 #endif 979 980 /*@ 981 MatViewFromOptions - View properties of the matrix based on options set in the options database 982 983 Collective 984 985 Input Parameters: 986 + A - the matrix 987 . obj - optional additional object that provides the options prefix to use 988 - name - command line option 989 990 Options Database Key: 991 . -mat_view [viewertype]:... - the viewer and its options 992 993 Level: intermediate 994 995 Note: 996 .vb 997 If no value is provided ascii:stdout is used 998 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 999 for example ascii::ascii_info prints just the information about the object not all details 1000 unless :append is given filename opens in write mode, overwriting what was already there 1001 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1002 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1003 socket[:port] defaults to the standard output port 1004 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1005 .ve 1006 1007 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1008 @*/ 1009 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1010 { 1011 PetscFunctionBegin; 1012 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1013 #if !defined(PETSC_HAVE_THREADSAFETY) 1014 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1015 #endif 1016 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1017 PetscFunctionReturn(PETSC_SUCCESS); 1018 } 1019 1020 /*@ 1021 MatView - display information about a matrix in a variety ways 1022 1023 Collective on viewer 1024 1025 Input Parameters: 1026 + mat - the matrix 1027 - viewer - visualization context 1028 1029 Options Database Keys: 1030 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1031 . -mat_view ::ascii_info_detail - Prints more detailed info 1032 . -mat_view - Prints matrix in ASCII format 1033 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1034 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1035 . -display <name> - Sets display name (default is host) 1036 . -draw_pause <sec> - Sets number of seconds to pause after display 1037 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1038 . -viewer_socket_machine <machine> - - 1039 . -viewer_socket_port <port> - - 1040 . -mat_view binary - save matrix to file in binary format 1041 - -viewer_binary_filename <name> - - 1042 1043 Level: beginner 1044 1045 Notes: 1046 The available visualization contexts include 1047 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1048 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1049 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1050 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1051 1052 The user can open alternative visualization contexts with 1053 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1054 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1055 specified file; corresponding input uses `MatLoad()` 1056 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1057 an X window display 1058 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1059 Currently only the `MATSEQDENSE` and `MATAIJ` 1060 matrix types support the Socket viewer. 1061 1062 The user can call `PetscViewerPushFormat()` to specify the output 1063 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1064 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1065 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1066 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1067 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1068 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1069 format common among all matrix types 1070 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1071 format (which is in many cases the same as the default) 1072 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1073 size and structure (not the matrix entries) 1074 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1075 the matrix structure (still not vector or matrix entries) 1076 1077 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1078 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1079 1080 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1081 1082 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1083 viewer is used. 1084 1085 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1086 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1087 1088 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1089 and then use the following mouse functions. 1090 .vb 1091 left mouse: zoom in 1092 middle mouse: zoom out 1093 right mouse: continue with the simulation 1094 .ve 1095 1096 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1097 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1098 @*/ 1099 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1100 { 1101 PetscInt rows, cols, rbs, cbs; 1102 PetscBool isascii, isstring, issaws; 1103 PetscViewerFormat format; 1104 PetscMPIInt size; 1105 1106 PetscFunctionBegin; 1107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1108 PetscValidType(mat, 1); 1109 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1110 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1111 1112 PetscCall(PetscViewerGetFormat(viewer, &format)); 1113 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1114 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1115 1116 #if !defined(PETSC_HAVE_THREADSAFETY) 1117 insidematview++; 1118 #endif 1119 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1120 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1121 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1122 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"); 1123 1124 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1125 if (isascii) { 1126 if (!mat->preallocated) { 1127 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1128 #if !defined(PETSC_HAVE_THREADSAFETY) 1129 insidematview--; 1130 #endif 1131 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1132 PetscFunctionReturn(PETSC_SUCCESS); 1133 } 1134 if (!mat->assembled) { 1135 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1136 #if !defined(PETSC_HAVE_THREADSAFETY) 1137 insidematview--; 1138 #endif 1139 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1140 PetscFunctionReturn(PETSC_SUCCESS); 1141 } 1142 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1143 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1144 MatNullSpace nullsp, transnullsp; 1145 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscCall(MatGetSize(mat, &rows, &cols)); 1148 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1149 if (rbs != 1 || cbs != 1) { 1150 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" : "")); 1151 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1152 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1153 if (mat->factortype) { 1154 MatSolverType solver; 1155 PetscCall(MatFactorGetSolverType(mat, &solver)); 1156 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1157 } 1158 if (mat->ops->getinfo) { 1159 MatInfo info; 1160 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1161 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1162 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1163 } 1164 PetscCall(MatGetNullSpace(mat, &nullsp)); 1165 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1166 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1167 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1168 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1169 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1170 PetscCall(PetscViewerASCIIPushTab(viewer)); 1171 PetscCall(MatProductView(mat, viewer)); 1172 PetscCall(PetscViewerASCIIPopTab(viewer)); 1173 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1174 IS tmp; 1175 1176 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1177 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1178 PetscCall(PetscViewerASCIIPushTab(viewer)); 1179 PetscCall(ISView(tmp, viewer)); 1180 PetscCall(PetscViewerASCIIPopTab(viewer)); 1181 PetscCall(ISDestroy(&tmp)); 1182 } 1183 } 1184 } else if (issaws) { 1185 #if defined(PETSC_HAVE_SAWS) 1186 PetscMPIInt rank; 1187 1188 PetscCall(PetscObjectName((PetscObject)mat)); 1189 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1190 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1191 #endif 1192 } else if (isstring) { 1193 const char *type; 1194 PetscCall(MatGetType(mat, &type)); 1195 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1196 PetscTryTypeMethod(mat, view, viewer); 1197 } 1198 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1199 PetscCall(PetscViewerASCIIPushTab(viewer)); 1200 PetscUseTypeMethod(mat, viewnative, viewer); 1201 PetscCall(PetscViewerASCIIPopTab(viewer)); 1202 } else if (mat->ops->view) { 1203 PetscCall(PetscViewerASCIIPushTab(viewer)); 1204 PetscUseTypeMethod(mat, view, viewer); 1205 PetscCall(PetscViewerASCIIPopTab(viewer)); 1206 } 1207 if (isascii) { 1208 PetscCall(PetscViewerGetFormat(viewer, &format)); 1209 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1210 } 1211 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1212 #if !defined(PETSC_HAVE_THREADSAFETY) 1213 insidematview--; 1214 #endif 1215 PetscFunctionReturn(PETSC_SUCCESS); 1216 } 1217 1218 #if defined(PETSC_USE_DEBUG) 1219 #include <../src/sys/totalview/tv_data_display.h> 1220 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1221 { 1222 TV_add_row("Local rows", "int", &mat->rmap->n); 1223 TV_add_row("Local columns", "int", &mat->cmap->n); 1224 TV_add_row("Global rows", "int", &mat->rmap->N); 1225 TV_add_row("Global columns", "int", &mat->cmap->N); 1226 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1227 return TV_format_OK; 1228 } 1229 #endif 1230 1231 /*@ 1232 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1233 with `MatView()`. The matrix format is determined from the options database. 1234 Generates a parallel MPI matrix if the communicator has more than one 1235 processor. The default matrix type is `MATAIJ`. 1236 1237 Collective 1238 1239 Input Parameters: 1240 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1241 or some related function before a call to `MatLoad()` 1242 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1243 1244 Options Database Key: 1245 . -matload_block_size <bs> - set block size 1246 1247 Level: beginner 1248 1249 Notes: 1250 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1251 `Mat` before calling this routine if you wish to set it from the options database. 1252 1253 `MatLoad()` automatically loads into the options database any options 1254 given in the file filename.info where filename is the name of the file 1255 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1256 file will be ignored if you use the -viewer_binary_skip_info option. 1257 1258 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1259 sets the default matrix type AIJ and sets the local and global sizes. 1260 If type and/or size is already set, then the same are used. 1261 1262 In parallel, each processor can load a subset of rows (or the 1263 entire matrix). This routine is especially useful when a large 1264 matrix is stored on disk and only part of it is desired on each 1265 processor. For example, a parallel solver may access only some of 1266 the rows from each processor. The algorithm used here reads 1267 relatively small blocks of data rather than reading the entire 1268 matrix and then subsetting it. 1269 1270 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1271 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1272 or the sequence like 1273 .vb 1274 `PetscViewer` v; 1275 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1276 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1277 `PetscViewerSetFromOptions`(v); 1278 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1279 `PetscViewerFileSetName`(v,"datafile"); 1280 .ve 1281 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1282 $ -viewer_type {binary, hdf5} 1283 1284 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1285 and src/mat/tutorials/ex10.c with the second approach. 1286 1287 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1288 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1289 Multiple objects, both matrices and vectors, can be stored within the same file. 1290 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1291 1292 Most users should not need to know the details of the binary storage 1293 format, since `MatLoad()` and `MatView()` completely hide these details. 1294 But for anyone who is interested, the standard binary matrix storage 1295 format is 1296 1297 .vb 1298 PetscInt MAT_FILE_CLASSID 1299 PetscInt number of rows 1300 PetscInt number of columns 1301 PetscInt total number of nonzeros 1302 PetscInt *number nonzeros in each row 1303 PetscInt *column indices of all nonzeros (starting index is zero) 1304 PetscScalar *values of all nonzeros 1305 .ve 1306 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1307 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 1308 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1309 1310 PETSc automatically does the byte swapping for 1311 machines that store the bytes reversed. Thus if you write your own binary 1312 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1313 and `PetscBinaryWrite()` to see how this may be done. 1314 1315 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1316 Each processor's chunk is loaded independently by its owning MPI process. 1317 Multiple objects, both matrices and vectors, can be stored within the same file. 1318 They are looked up by their PetscObject name. 1319 1320 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1321 by default the same structure and naming of the AIJ arrays and column count 1322 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1323 $ save example.mat A b -v7.3 1324 can be directly read by this routine (see Reference 1 for details). 1325 1326 Depending on your MATLAB version, this format might be a default, 1327 otherwise you can set it as default in Preferences. 1328 1329 Unless -nocompression flag is used to save the file in MATLAB, 1330 PETSc must be configured with ZLIB package. 1331 1332 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1333 1334 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1335 1336 Corresponding `MatView()` is not yet implemented. 1337 1338 The loaded matrix is actually a transpose of the original one in MATLAB, 1339 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1340 With this format, matrix is automatically transposed by PETSc, 1341 unless the matrix is marked as SPD or symmetric 1342 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1343 1344 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1345 1346 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1347 @*/ 1348 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1349 { 1350 PetscBool flg; 1351 1352 PetscFunctionBegin; 1353 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1354 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1355 1356 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1357 1358 flg = PETSC_FALSE; 1359 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1360 if (flg) { 1361 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1362 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1363 } 1364 flg = PETSC_FALSE; 1365 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1366 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1367 1368 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1369 PetscUseTypeMethod(mat, load, viewer); 1370 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1371 PetscFunctionReturn(PETSC_SUCCESS); 1372 } 1373 1374 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1375 { 1376 Mat_Redundant *redund = *redundant; 1377 1378 PetscFunctionBegin; 1379 if (redund) { 1380 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1381 PetscCall(ISDestroy(&redund->isrow)); 1382 PetscCall(ISDestroy(&redund->iscol)); 1383 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1384 } else { 1385 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1386 PetscCall(PetscFree(redund->sbuf_j)); 1387 PetscCall(PetscFree(redund->sbuf_a)); 1388 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1389 PetscCall(PetscFree(redund->rbuf_j[i])); 1390 PetscCall(PetscFree(redund->rbuf_a[i])); 1391 } 1392 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1393 } 1394 1395 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1396 PetscCall(PetscFree(redund)); 1397 } 1398 PetscFunctionReturn(PETSC_SUCCESS); 1399 } 1400 1401 /*@ 1402 MatDestroy - Frees space taken by a matrix. 1403 1404 Collective 1405 1406 Input Parameter: 1407 . A - the matrix 1408 1409 Level: beginner 1410 1411 Developer Note: 1412 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1413 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1414 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1415 if changes are needed here. 1416 1417 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1418 @*/ 1419 PetscErrorCode MatDestroy(Mat *A) 1420 { 1421 PetscFunctionBegin; 1422 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1423 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1424 if (--((PetscObject)*A)->refct > 0) { 1425 *A = NULL; 1426 PetscFunctionReturn(PETSC_SUCCESS); 1427 } 1428 1429 /* if memory was published with SAWs then destroy it */ 1430 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1431 PetscTryTypeMethod(*A, destroy); 1432 1433 PetscCall(PetscFree((*A)->factorprefix)); 1434 PetscCall(PetscFree((*A)->defaultvectype)); 1435 PetscCall(PetscFree((*A)->defaultrandtype)); 1436 PetscCall(PetscFree((*A)->bsizes)); 1437 PetscCall(PetscFree((*A)->solvertype)); 1438 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1439 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1440 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1441 PetscCall(MatProductClear(*A)); 1442 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1443 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1444 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1445 PetscCall(MatDestroy(&(*A)->schur)); 1446 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1447 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1448 PetscCall(PetscHeaderDestroy(A)); 1449 PetscFunctionReturn(PETSC_SUCCESS); 1450 } 1451 1452 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1453 /*@ 1454 MatSetValues - Inserts or adds a block of values into a matrix. 1455 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1456 MUST be called after all calls to `MatSetValues()` have been completed. 1457 1458 Not Collective 1459 1460 Input Parameters: 1461 + mat - the matrix 1462 . v - a logically two-dimensional array of values 1463 . m - the number of rows 1464 . idxm - the global indices of the rows 1465 . n - the number of columns 1466 . idxn - the global indices of the columns 1467 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1468 1469 Level: beginner 1470 1471 Notes: 1472 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1473 1474 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1475 options cannot be mixed without intervening calls to the assembly 1476 routines. 1477 1478 `MatSetValues()` uses 0-based row and column numbers in Fortran 1479 as well as in C. 1480 1481 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1482 simply ignored. This allows easily inserting element stiffness matrices 1483 with homogeneous Dirichlet boundary conditions that you don't want represented 1484 in the matrix. 1485 1486 Efficiency Alert: 1487 The routine `MatSetValuesBlocked()` may offer much better efficiency 1488 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1489 1490 Fortran Notes: 1491 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1492 .vb 1493 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1494 .ve 1495 1496 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1497 1498 Developer Note: 1499 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1500 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1501 1502 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1503 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1504 @*/ 1505 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1506 { 1507 PetscFunctionBeginHot; 1508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1509 PetscValidType(mat, 1); 1510 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1511 PetscAssertPointer(idxm, 3); 1512 PetscAssertPointer(idxn, 5); 1513 MatCheckPreallocated(mat, 1); 1514 1515 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1516 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1517 1518 if (PetscDefined(USE_DEBUG)) { 1519 PetscInt i, j; 1520 1521 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1522 if (v) { 1523 for (i = 0; i < m; i++) { 1524 for (j = 0; j < n; j++) { 1525 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1526 #if defined(PETSC_USE_COMPLEX) 1527 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]); 1528 #else 1529 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]); 1530 #endif 1531 } 1532 } 1533 } 1534 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); 1535 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); 1536 } 1537 1538 if (mat->assembled) { 1539 mat->was_assembled = PETSC_TRUE; 1540 mat->assembled = PETSC_FALSE; 1541 } 1542 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1543 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1544 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1545 PetscFunctionReturn(PETSC_SUCCESS); 1546 } 1547 1548 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1549 /*@ 1550 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1551 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1552 MUST be called after all calls to `MatSetValues()` have been completed. 1553 1554 Not Collective 1555 1556 Input Parameters: 1557 + mat - the matrix 1558 . v - a logically two-dimensional array of values 1559 . ism - the rows to provide 1560 . isn - the columns to provide 1561 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1562 1563 Level: beginner 1564 1565 Notes: 1566 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1567 1568 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1569 options cannot be mixed without intervening calls to the assembly 1570 routines. 1571 1572 `MatSetValues()` uses 0-based row and column numbers in Fortran 1573 as well as in C. 1574 1575 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1576 simply ignored. This allows easily inserting element stiffness matrices 1577 with homogeneous Dirichlet boundary conditions that you don't want represented 1578 in the matrix. 1579 1580 Efficiency Alert: 1581 The routine `MatSetValuesBlocked()` may offer much better efficiency 1582 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1583 1584 This is currently not optimized for any particular `ISType` 1585 1586 Developer Note: 1587 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1588 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1589 1590 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1591 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1592 @*/ 1593 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1594 { 1595 PetscInt m, n; 1596 const PetscInt *rows, *cols; 1597 1598 PetscFunctionBeginHot; 1599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1600 PetscCall(ISGetIndices(ism, &rows)); 1601 PetscCall(ISGetIndices(isn, &cols)); 1602 PetscCall(ISGetLocalSize(ism, &m)); 1603 PetscCall(ISGetLocalSize(isn, &n)); 1604 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1605 PetscCall(ISRestoreIndices(ism, &rows)); 1606 PetscCall(ISRestoreIndices(isn, &cols)); 1607 PetscFunctionReturn(PETSC_SUCCESS); 1608 } 1609 1610 /*@ 1611 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1612 values into a matrix 1613 1614 Not Collective 1615 1616 Input Parameters: 1617 + mat - the matrix 1618 . row - the (block) row to set 1619 - v - a logically two-dimensional array of values 1620 1621 Level: intermediate 1622 1623 Notes: 1624 The values, `v`, are column-oriented (for the block version) and sorted 1625 1626 All the nonzero values in `row` must be provided 1627 1628 The matrix must have previously had its column indices set, likely by having been assembled. 1629 1630 `row` must belong to this MPI process 1631 1632 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1633 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1634 @*/ 1635 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1636 { 1637 PetscInt globalrow; 1638 1639 PetscFunctionBegin; 1640 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1641 PetscValidType(mat, 1); 1642 PetscAssertPointer(v, 3); 1643 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1644 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1645 PetscFunctionReturn(PETSC_SUCCESS); 1646 } 1647 1648 /*@ 1649 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1650 values into a matrix 1651 1652 Not Collective 1653 1654 Input Parameters: 1655 + mat - the matrix 1656 . row - the (block) row to set 1657 - 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 1658 1659 Level: advanced 1660 1661 Notes: 1662 The values, `v`, are column-oriented for the block version. 1663 1664 All the nonzeros in `row` must be provided 1665 1666 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1667 1668 `row` must belong to this process 1669 1670 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1671 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1672 @*/ 1673 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1674 { 1675 PetscFunctionBeginHot; 1676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1677 PetscValidType(mat, 1); 1678 MatCheckPreallocated(mat, 1); 1679 PetscAssertPointer(v, 3); 1680 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1681 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1682 mat->insertmode = INSERT_VALUES; 1683 1684 if (mat->assembled) { 1685 mat->was_assembled = PETSC_TRUE; 1686 mat->assembled = PETSC_FALSE; 1687 } 1688 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1689 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1690 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1691 PetscFunctionReturn(PETSC_SUCCESS); 1692 } 1693 1694 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1695 /*@ 1696 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1697 Using structured grid indexing 1698 1699 Not Collective 1700 1701 Input Parameters: 1702 + mat - the matrix 1703 . m - number of rows being entered 1704 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1705 . n - number of columns being entered 1706 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1707 . v - a logically two-dimensional array of values 1708 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1709 1710 Level: beginner 1711 1712 Notes: 1713 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1714 1715 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1716 options cannot be mixed without intervening calls to the assembly 1717 routines. 1718 1719 The grid coordinates are across the entire grid, not just the local portion 1720 1721 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1722 as well as in C. 1723 1724 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1725 1726 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1727 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1728 1729 The columns and rows in the stencil passed in MUST be contained within the 1730 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1731 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1732 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1733 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1734 1735 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1736 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1737 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1738 `DM_BOUNDARY_PERIODIC` boundary type. 1739 1740 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 1741 a single value per point) you can skip filling those indices. 1742 1743 Inspired by the structured grid interface to the HYPRE package 1744 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1745 1746 Efficiency Alert: 1747 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1748 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1749 1750 Fortran Note: 1751 `idxm` and `idxn` should be declared as 1752 $ MatStencil idxm(4,m),idxn(4,n) 1753 and the values inserted using 1754 .vb 1755 idxm(MatStencil_i,1) = i 1756 idxm(MatStencil_j,1) = j 1757 idxm(MatStencil_k,1) = k 1758 idxm(MatStencil_c,1) = c 1759 etc 1760 .ve 1761 1762 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1763 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1764 @*/ 1765 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1766 { 1767 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1768 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1769 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1770 1771 PetscFunctionBegin; 1772 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1774 PetscValidType(mat, 1); 1775 PetscAssertPointer(idxm, 3); 1776 PetscAssertPointer(idxn, 5); 1777 1778 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1779 jdxm = buf; 1780 jdxn = buf + m; 1781 } else { 1782 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1783 jdxm = bufm; 1784 jdxn = bufn; 1785 } 1786 for (i = 0; i < m; i++) { 1787 for (j = 0; j < 3 - sdim; j++) dxm++; 1788 tmp = *dxm++ - starts[0]; 1789 for (j = 0; j < dim - 1; j++) { 1790 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1791 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1792 } 1793 if (mat->stencil.noc) dxm++; 1794 jdxm[i] = tmp; 1795 } 1796 for (i = 0; i < n; i++) { 1797 for (j = 0; j < 3 - sdim; j++) dxn++; 1798 tmp = *dxn++ - starts[0]; 1799 for (j = 0; j < dim - 1; j++) { 1800 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1801 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1802 } 1803 if (mat->stencil.noc) dxn++; 1804 jdxn[i] = tmp; 1805 } 1806 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1807 PetscCall(PetscFree2(bufm, bufn)); 1808 PetscFunctionReturn(PETSC_SUCCESS); 1809 } 1810 1811 /*@ 1812 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1813 Using structured grid indexing 1814 1815 Not Collective 1816 1817 Input Parameters: 1818 + mat - the matrix 1819 . m - number of rows being entered 1820 . idxm - grid coordinates for matrix rows being entered 1821 . n - number of columns being entered 1822 . idxn - grid coordinates for matrix columns being entered 1823 . v - a logically two-dimensional array of values 1824 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1825 1826 Level: beginner 1827 1828 Notes: 1829 By default the values, `v`, are row-oriented and unsorted. 1830 See `MatSetOption()` for other options. 1831 1832 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1833 options cannot be mixed without intervening calls to the assembly 1834 routines. 1835 1836 The grid coordinates are across the entire grid, not just the local portion 1837 1838 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1839 as well as in C. 1840 1841 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1842 1843 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1844 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1845 1846 The columns and rows in the stencil passed in MUST be contained within the 1847 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1848 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1849 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1850 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1851 1852 Negative indices may be passed in idxm and idxn, these rows and columns are 1853 simply ignored. This allows easily inserting element stiffness matrices 1854 with homogeneous Dirichlet boundary conditions that you don't want represented 1855 in the matrix. 1856 1857 Inspired by the structured grid interface to the HYPRE package 1858 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1859 1860 Fortran Note: 1861 `idxm` and `idxn` should be declared as 1862 $ MatStencil idxm(4,m),idxn(4,n) 1863 and the values inserted using 1864 .vb 1865 idxm(MatStencil_i,1) = i 1866 idxm(MatStencil_j,1) = j 1867 idxm(MatStencil_k,1) = k 1868 etc 1869 .ve 1870 1871 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1872 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1873 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1874 @*/ 1875 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1876 { 1877 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1878 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1879 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1880 1881 PetscFunctionBegin; 1882 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1884 PetscValidType(mat, 1); 1885 PetscAssertPointer(idxm, 3); 1886 PetscAssertPointer(idxn, 5); 1887 PetscAssertPointer(v, 6); 1888 1889 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1890 jdxm = buf; 1891 jdxn = buf + m; 1892 } else { 1893 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1894 jdxm = bufm; 1895 jdxn = bufn; 1896 } 1897 for (i = 0; i < m; i++) { 1898 for (j = 0; j < 3 - sdim; j++) dxm++; 1899 tmp = *dxm++ - starts[0]; 1900 for (j = 0; j < sdim - 1; j++) { 1901 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1902 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1903 } 1904 dxm++; 1905 jdxm[i] = tmp; 1906 } 1907 for (i = 0; i < n; i++) { 1908 for (j = 0; j < 3 - sdim; j++) dxn++; 1909 tmp = *dxn++ - starts[0]; 1910 for (j = 0; j < sdim - 1; j++) { 1911 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1912 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1913 } 1914 dxn++; 1915 jdxn[i] = tmp; 1916 } 1917 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1918 PetscCall(PetscFree2(bufm, bufn)); 1919 PetscFunctionReturn(PETSC_SUCCESS); 1920 } 1921 1922 /*@ 1923 MatSetStencil - Sets the grid information for setting values into a matrix via 1924 `MatSetValuesStencil()` 1925 1926 Not Collective 1927 1928 Input Parameters: 1929 + mat - the matrix 1930 . dim - dimension of the grid 1, 2, or 3 1931 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1932 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1933 - dof - number of degrees of freedom per node 1934 1935 Level: beginner 1936 1937 Notes: 1938 Inspired by the structured grid interface to the HYPRE package 1939 (www.llnl.gov/CASC/hyper) 1940 1941 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1942 user. 1943 1944 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1945 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1946 @*/ 1947 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1948 { 1949 PetscFunctionBegin; 1950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1951 PetscAssertPointer(dims, 3); 1952 PetscAssertPointer(starts, 4); 1953 1954 mat->stencil.dim = dim + (dof > 1); 1955 for (PetscInt i = 0; i < dim; i++) { 1956 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1957 mat->stencil.starts[i] = starts[dim - i - 1]; 1958 } 1959 mat->stencil.dims[dim] = dof; 1960 mat->stencil.starts[dim] = 0; 1961 mat->stencil.noc = (PetscBool)(dof == 1); 1962 PetscFunctionReturn(PETSC_SUCCESS); 1963 } 1964 1965 /*@ 1966 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1967 1968 Not Collective 1969 1970 Input Parameters: 1971 + mat - the matrix 1972 . v - a logically two-dimensional array of values 1973 . m - the number of block rows 1974 . idxm - the global block indices 1975 . n - the number of block columns 1976 . idxn - the global block indices 1977 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1978 1979 Level: intermediate 1980 1981 Notes: 1982 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1983 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1984 1985 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1986 NOT the total number of rows/columns; for example, if the block size is 2 and 1987 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1988 The values in `idxm` would be 1 2; that is the first index for each block divided by 1989 the block size. 1990 1991 You must call `MatSetBlockSize()` when constructing this matrix (before 1992 preallocating it). 1993 1994 By default the values, `v`, are row-oriented, so the layout of 1995 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1996 1997 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1998 options cannot be mixed without intervening calls to the assembly 1999 routines. 2000 2001 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2002 as well as in C. 2003 2004 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2005 simply ignored. This allows easily inserting element stiffness matrices 2006 with homogeneous Dirichlet boundary conditions that you don't want represented 2007 in the matrix. 2008 2009 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2010 internal searching must be done to determine where to place the 2011 data in the matrix storage space. By instead inserting blocks of 2012 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2013 reduced. 2014 2015 Example: 2016 .vb 2017 Suppose m=n=2 and block size(bs) = 2 The array is 2018 2019 1 2 | 3 4 2020 5 6 | 7 8 2021 - - - | - - - 2022 9 10 | 11 12 2023 13 14 | 15 16 2024 2025 v[] should be passed in like 2026 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2027 2028 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2029 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2030 .ve 2031 2032 Fortran Notes: 2033 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2034 .vb 2035 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2036 .ve 2037 2038 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2039 2040 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2041 @*/ 2042 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2043 { 2044 PetscFunctionBeginHot; 2045 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2046 PetscValidType(mat, 1); 2047 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2048 PetscAssertPointer(idxm, 3); 2049 PetscAssertPointer(idxn, 5); 2050 MatCheckPreallocated(mat, 1); 2051 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2052 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2053 if (PetscDefined(USE_DEBUG)) { 2054 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2055 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2056 } 2057 if (PetscDefined(USE_DEBUG)) { 2058 PetscInt rbs, cbs, M, N, i; 2059 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2060 PetscCall(MatGetSize(mat, &M, &N)); 2061 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); 2062 for (i = 0; i < n; i++) 2063 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); 2064 } 2065 if (mat->assembled) { 2066 mat->was_assembled = PETSC_TRUE; 2067 mat->assembled = PETSC_FALSE; 2068 } 2069 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2070 if (mat->ops->setvaluesblocked) { 2071 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2072 } else { 2073 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2074 PetscInt i, j, bs, cbs; 2075 2076 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2077 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2078 iidxm = buf; 2079 iidxn = buf + m * bs; 2080 } else { 2081 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2082 iidxm = bufr; 2083 iidxn = bufc; 2084 } 2085 for (i = 0; i < m; i++) { 2086 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2087 } 2088 if (m != n || bs != cbs || idxm != idxn) { 2089 for (i = 0; i < n; i++) { 2090 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2091 } 2092 } else iidxn = iidxm; 2093 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2094 PetscCall(PetscFree2(bufr, bufc)); 2095 } 2096 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2097 PetscFunctionReturn(PETSC_SUCCESS); 2098 } 2099 2100 /*@ 2101 MatGetValues - Gets a block of local values from a matrix. 2102 2103 Not Collective; can only return values that are owned by the give process 2104 2105 Input Parameters: 2106 + mat - the matrix 2107 . v - a logically two-dimensional array for storing the values 2108 . m - the number of rows 2109 . idxm - the global indices of the rows 2110 . n - the number of columns 2111 - idxn - the global indices of the columns 2112 2113 Level: advanced 2114 2115 Notes: 2116 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2117 The values, `v`, are then returned in a row-oriented format, 2118 analogous to that used by default in `MatSetValues()`. 2119 2120 `MatGetValues()` uses 0-based row and column numbers in 2121 Fortran as well as in C. 2122 2123 `MatGetValues()` requires that the matrix has been assembled 2124 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2125 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2126 without intermediate matrix assembly. 2127 2128 Negative row or column indices will be ignored and those locations in `v` will be 2129 left unchanged. 2130 2131 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2132 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2133 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2134 2135 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2136 @*/ 2137 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2138 { 2139 PetscFunctionBegin; 2140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2141 PetscValidType(mat, 1); 2142 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2143 PetscAssertPointer(idxm, 3); 2144 PetscAssertPointer(idxn, 5); 2145 PetscAssertPointer(v, 6); 2146 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2147 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2148 MatCheckPreallocated(mat, 1); 2149 2150 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2151 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2152 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2153 PetscFunctionReturn(PETSC_SUCCESS); 2154 } 2155 2156 /*@ 2157 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2158 defined previously by `MatSetLocalToGlobalMapping()` 2159 2160 Not Collective 2161 2162 Input Parameters: 2163 + mat - the matrix 2164 . nrow - number of rows 2165 . irow - the row local indices 2166 . ncol - number of columns 2167 - icol - the column local indices 2168 2169 Output Parameter: 2170 . y - a logically two-dimensional array of values 2171 2172 Level: advanced 2173 2174 Notes: 2175 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2176 2177 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, 2178 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2179 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2180 with `MatSetLocalToGlobalMapping()`. 2181 2182 Developer Note: 2183 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2184 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2185 2186 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2187 `MatSetValuesLocal()`, `MatGetValues()` 2188 @*/ 2189 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2190 { 2191 PetscFunctionBeginHot; 2192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2193 PetscValidType(mat, 1); 2194 MatCheckPreallocated(mat, 1); 2195 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2196 PetscAssertPointer(irow, 3); 2197 PetscAssertPointer(icol, 5); 2198 if (PetscDefined(USE_DEBUG)) { 2199 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2200 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2201 } 2202 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2203 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2204 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2205 else { 2206 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2207 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2208 irowm = buf; 2209 icolm = buf + nrow; 2210 } else { 2211 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2212 irowm = bufr; 2213 icolm = bufc; 2214 } 2215 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2216 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2217 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2218 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2219 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2220 PetscCall(PetscFree2(bufr, bufc)); 2221 } 2222 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2223 PetscFunctionReturn(PETSC_SUCCESS); 2224 } 2225 2226 /*@ 2227 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2228 the same size. Currently, this can only be called once and creates the given matrix. 2229 2230 Not Collective 2231 2232 Input Parameters: 2233 + mat - the matrix 2234 . nb - the number of blocks 2235 . bs - the number of rows (and columns) in each block 2236 . rows - a concatenation of the rows for each block 2237 - v - a concatenation of logically two-dimensional arrays of values 2238 2239 Level: advanced 2240 2241 Notes: 2242 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2243 2244 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2245 2246 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2247 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2248 @*/ 2249 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2250 { 2251 PetscFunctionBegin; 2252 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2253 PetscValidType(mat, 1); 2254 PetscAssertPointer(rows, 4); 2255 PetscAssertPointer(v, 5); 2256 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2257 2258 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2259 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2260 else { 2261 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2262 } 2263 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2264 PetscFunctionReturn(PETSC_SUCCESS); 2265 } 2266 2267 /*@ 2268 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2269 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2270 using a local (per-processor) numbering. 2271 2272 Not Collective 2273 2274 Input Parameters: 2275 + x - the matrix 2276 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2277 - cmapping - column mapping 2278 2279 Level: intermediate 2280 2281 Note: 2282 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2283 2284 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2285 @*/ 2286 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2287 { 2288 PetscFunctionBegin; 2289 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2290 PetscValidType(x, 1); 2291 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2292 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2293 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2294 else { 2295 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2296 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2297 } 2298 PetscFunctionReturn(PETSC_SUCCESS); 2299 } 2300 2301 /*@ 2302 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2303 2304 Not Collective 2305 2306 Input Parameter: 2307 . A - the matrix 2308 2309 Output Parameters: 2310 + rmapping - row mapping 2311 - cmapping - column mapping 2312 2313 Level: advanced 2314 2315 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2316 @*/ 2317 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2318 { 2319 PetscFunctionBegin; 2320 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2321 PetscValidType(A, 1); 2322 if (rmapping) { 2323 PetscAssertPointer(rmapping, 2); 2324 *rmapping = A->rmap->mapping; 2325 } 2326 if (cmapping) { 2327 PetscAssertPointer(cmapping, 3); 2328 *cmapping = A->cmap->mapping; 2329 } 2330 PetscFunctionReturn(PETSC_SUCCESS); 2331 } 2332 2333 /*@ 2334 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2335 2336 Logically Collective 2337 2338 Input Parameters: 2339 + A - the matrix 2340 . rmap - row layout 2341 - cmap - column layout 2342 2343 Level: advanced 2344 2345 Note: 2346 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2347 2348 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2349 @*/ 2350 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2351 { 2352 PetscFunctionBegin; 2353 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2354 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2355 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2356 PetscFunctionReturn(PETSC_SUCCESS); 2357 } 2358 2359 /*@ 2360 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2361 2362 Not Collective 2363 2364 Input Parameter: 2365 . A - the matrix 2366 2367 Output Parameters: 2368 + rmap - row layout 2369 - cmap - column layout 2370 2371 Level: advanced 2372 2373 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2374 @*/ 2375 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2376 { 2377 PetscFunctionBegin; 2378 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2379 PetscValidType(A, 1); 2380 if (rmap) { 2381 PetscAssertPointer(rmap, 2); 2382 *rmap = A->rmap; 2383 } 2384 if (cmap) { 2385 PetscAssertPointer(cmap, 3); 2386 *cmap = A->cmap; 2387 } 2388 PetscFunctionReturn(PETSC_SUCCESS); 2389 } 2390 2391 /*@ 2392 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2393 using a local numbering of the rows and columns. 2394 2395 Not Collective 2396 2397 Input Parameters: 2398 + mat - the matrix 2399 . nrow - number of rows 2400 . irow - the row local indices 2401 . ncol - number of columns 2402 . icol - the column local indices 2403 . y - a logically two-dimensional array of values 2404 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2405 2406 Level: intermediate 2407 2408 Notes: 2409 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2410 2411 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2412 options cannot be mixed without intervening calls to the assembly 2413 routines. 2414 2415 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2416 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2417 2418 Fortran Notes: 2419 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2420 .vb 2421 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2422 .ve 2423 2424 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2425 2426 Developer Note: 2427 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2428 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2429 2430 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2431 `MatGetValuesLocal()` 2432 @*/ 2433 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2434 { 2435 PetscFunctionBeginHot; 2436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2437 PetscValidType(mat, 1); 2438 MatCheckPreallocated(mat, 1); 2439 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2440 PetscAssertPointer(irow, 3); 2441 PetscAssertPointer(icol, 5); 2442 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2443 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2444 if (PetscDefined(USE_DEBUG)) { 2445 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2446 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2447 } 2448 2449 if (mat->assembled) { 2450 mat->was_assembled = PETSC_TRUE; 2451 mat->assembled = PETSC_FALSE; 2452 } 2453 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2454 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2455 else { 2456 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2457 const PetscInt *irowm, *icolm; 2458 2459 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2460 bufr = buf; 2461 bufc = buf + nrow; 2462 irowm = bufr; 2463 icolm = bufc; 2464 } else { 2465 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2466 irowm = bufr; 2467 icolm = bufc; 2468 } 2469 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2470 else irowm = irow; 2471 if (mat->cmap->mapping) { 2472 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2473 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2474 } else icolm = irowm; 2475 } else icolm = icol; 2476 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2477 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2478 } 2479 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2480 PetscFunctionReturn(PETSC_SUCCESS); 2481 } 2482 2483 /*@ 2484 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2485 using a local ordering of the nodes a block at a time. 2486 2487 Not Collective 2488 2489 Input Parameters: 2490 + mat - the matrix 2491 . nrow - number of rows 2492 . irow - the row local indices 2493 . ncol - number of columns 2494 . icol - the column local indices 2495 . y - a logically two-dimensional array of values 2496 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2497 2498 Level: intermediate 2499 2500 Notes: 2501 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2502 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2503 2504 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2505 options cannot be mixed without intervening calls to the assembly 2506 routines. 2507 2508 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2509 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2510 2511 Fortran Notes: 2512 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2513 .vb 2514 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2515 .ve 2516 2517 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2518 2519 Developer Note: 2520 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2521 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2522 2523 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2524 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2525 @*/ 2526 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2527 { 2528 PetscFunctionBeginHot; 2529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2530 PetscValidType(mat, 1); 2531 MatCheckPreallocated(mat, 1); 2532 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2533 PetscAssertPointer(irow, 3); 2534 PetscAssertPointer(icol, 5); 2535 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2536 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2537 if (PetscDefined(USE_DEBUG)) { 2538 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2539 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); 2540 } 2541 2542 if (mat->assembled) { 2543 mat->was_assembled = PETSC_TRUE; 2544 mat->assembled = PETSC_FALSE; 2545 } 2546 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2547 PetscInt irbs, rbs; 2548 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2549 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2550 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2551 } 2552 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2553 PetscInt icbs, cbs; 2554 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2555 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2556 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2557 } 2558 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2559 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2560 else { 2561 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2562 const PetscInt *irowm, *icolm; 2563 2564 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2565 bufr = buf; 2566 bufc = buf + nrow; 2567 irowm = bufr; 2568 icolm = bufc; 2569 } else { 2570 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2571 irowm = bufr; 2572 icolm = bufc; 2573 } 2574 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2575 else irowm = irow; 2576 if (mat->cmap->mapping) { 2577 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2578 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2579 } else icolm = irowm; 2580 } else icolm = icol; 2581 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2582 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2583 } 2584 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2585 PetscFunctionReturn(PETSC_SUCCESS); 2586 } 2587 2588 /*@ 2589 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2590 2591 Collective 2592 2593 Input Parameters: 2594 + mat - the matrix 2595 - x - the vector to be multiplied 2596 2597 Output Parameter: 2598 . y - the result 2599 2600 Level: developer 2601 2602 Note: 2603 The vectors `x` and `y` cannot be the same. I.e., one cannot 2604 call `MatMultDiagonalBlock`(A,y,y). 2605 2606 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2607 @*/ 2608 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2609 { 2610 PetscFunctionBegin; 2611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2612 PetscValidType(mat, 1); 2613 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2614 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2615 2616 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2617 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2618 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2619 MatCheckPreallocated(mat, 1); 2620 2621 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2622 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2623 PetscFunctionReturn(PETSC_SUCCESS); 2624 } 2625 2626 /*@ 2627 MatMult - Computes the matrix-vector product, $y = Ax$. 2628 2629 Neighbor-wise Collective 2630 2631 Input Parameters: 2632 + mat - the matrix 2633 - x - the vector to be multiplied 2634 2635 Output Parameter: 2636 . y - the result 2637 2638 Level: beginner 2639 2640 Note: 2641 The vectors `x` and `y` cannot be the same. I.e., one cannot 2642 call `MatMult`(A,y,y). 2643 2644 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2645 @*/ 2646 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2647 { 2648 PetscFunctionBegin; 2649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2650 PetscValidType(mat, 1); 2651 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2652 VecCheckAssembled(x); 2653 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2654 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2655 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2656 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2657 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); 2658 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); 2659 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); 2660 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); 2661 PetscCall(VecSetErrorIfLocked(y, 3)); 2662 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2663 MatCheckPreallocated(mat, 1); 2664 2665 PetscCall(VecLockReadPush(x)); 2666 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2667 PetscUseTypeMethod(mat, mult, x, y); 2668 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2669 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2670 PetscCall(VecLockReadPop(x)); 2671 PetscFunctionReturn(PETSC_SUCCESS); 2672 } 2673 2674 /*@ 2675 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2676 2677 Neighbor-wise Collective 2678 2679 Input Parameters: 2680 + mat - the matrix 2681 - x - the vector to be multiplied 2682 2683 Output Parameter: 2684 . y - the result 2685 2686 Level: beginner 2687 2688 Notes: 2689 The vectors `x` and `y` cannot be the same. I.e., one cannot 2690 call `MatMultTranspose`(A,y,y). 2691 2692 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2693 use `MatMultHermitianTranspose()` 2694 2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2696 @*/ 2697 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2698 { 2699 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2700 2701 PetscFunctionBegin; 2702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2703 PetscValidType(mat, 1); 2704 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2705 VecCheckAssembled(x); 2706 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2707 2708 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2709 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2710 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2711 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); 2712 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); 2713 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); 2714 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); 2715 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2716 MatCheckPreallocated(mat, 1); 2717 2718 if (!mat->ops->multtranspose) { 2719 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2720 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); 2721 } else op = mat->ops->multtranspose; 2722 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2723 PetscCall(VecLockReadPush(x)); 2724 PetscCall((*op)(mat, x, y)); 2725 PetscCall(VecLockReadPop(x)); 2726 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2727 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2728 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2729 PetscFunctionReturn(PETSC_SUCCESS); 2730 } 2731 2732 /*@ 2733 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2734 2735 Neighbor-wise Collective 2736 2737 Input Parameters: 2738 + mat - the matrix 2739 - x - the vector to be multiplied 2740 2741 Output Parameter: 2742 . y - the result 2743 2744 Level: beginner 2745 2746 Notes: 2747 The vectors `x` and `y` cannot be the same. I.e., one cannot 2748 call `MatMultHermitianTranspose`(A,y,y). 2749 2750 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2751 2752 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2753 2754 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2755 @*/ 2756 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2757 { 2758 PetscFunctionBegin; 2759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2760 PetscValidType(mat, 1); 2761 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2762 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2763 2764 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2765 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2766 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2767 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); 2768 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); 2769 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); 2770 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); 2771 MatCheckPreallocated(mat, 1); 2772 2773 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2774 #if defined(PETSC_USE_COMPLEX) 2775 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2776 PetscCall(VecLockReadPush(x)); 2777 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2778 else PetscUseTypeMethod(mat, mult, x, y); 2779 PetscCall(VecLockReadPop(x)); 2780 } else { 2781 Vec w; 2782 PetscCall(VecDuplicate(x, &w)); 2783 PetscCall(VecCopy(x, w)); 2784 PetscCall(VecConjugate(w)); 2785 PetscCall(MatMultTranspose(mat, w, y)); 2786 PetscCall(VecDestroy(&w)); 2787 PetscCall(VecConjugate(y)); 2788 } 2789 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2790 #else 2791 PetscCall(MatMultTranspose(mat, x, y)); 2792 #endif 2793 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2794 PetscFunctionReturn(PETSC_SUCCESS); 2795 } 2796 2797 /*@ 2798 MatMultAdd - Computes $v3 = v2 + A * v1$. 2799 2800 Neighbor-wise Collective 2801 2802 Input Parameters: 2803 + mat - the matrix 2804 . v1 - the vector to be multiplied by `mat` 2805 - v2 - the vector to be added to the result 2806 2807 Output Parameter: 2808 . v3 - the result 2809 2810 Level: beginner 2811 2812 Note: 2813 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2814 call `MatMultAdd`(A,v1,v2,v1). 2815 2816 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2817 @*/ 2818 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2819 { 2820 PetscFunctionBegin; 2821 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2822 PetscValidType(mat, 1); 2823 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2824 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2825 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2826 2827 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2828 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2829 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); 2830 /* 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); 2831 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); */ 2832 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); 2833 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); 2834 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2835 MatCheckPreallocated(mat, 1); 2836 2837 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2838 PetscCall(VecLockReadPush(v1)); 2839 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2840 PetscCall(VecLockReadPop(v1)); 2841 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2842 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2843 PetscFunctionReturn(PETSC_SUCCESS); 2844 } 2845 2846 /*@ 2847 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2848 2849 Neighbor-wise Collective 2850 2851 Input Parameters: 2852 + mat - the matrix 2853 . v1 - the vector to be multiplied by the transpose of the matrix 2854 - v2 - the vector to be added to the result 2855 2856 Output Parameter: 2857 . v3 - the result 2858 2859 Level: beginner 2860 2861 Note: 2862 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2863 call `MatMultTransposeAdd`(A,v1,v2,v1). 2864 2865 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2866 @*/ 2867 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2868 { 2869 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2870 2871 PetscFunctionBegin; 2872 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2873 PetscValidType(mat, 1); 2874 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2875 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2876 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2877 2878 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2879 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2880 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); 2881 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); 2882 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); 2883 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2884 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2885 MatCheckPreallocated(mat, 1); 2886 2887 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2888 PetscCall(VecLockReadPush(v1)); 2889 PetscCall((*op)(mat, v1, v2, v3)); 2890 PetscCall(VecLockReadPop(v1)); 2891 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2892 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2893 PetscFunctionReturn(PETSC_SUCCESS); 2894 } 2895 2896 /*@ 2897 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2898 2899 Neighbor-wise Collective 2900 2901 Input Parameters: 2902 + mat - the matrix 2903 . v1 - the vector to be multiplied by the Hermitian transpose 2904 - v2 - the vector to be added to the result 2905 2906 Output Parameter: 2907 . v3 - the result 2908 2909 Level: beginner 2910 2911 Note: 2912 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2913 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2914 2915 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2916 @*/ 2917 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2918 { 2919 PetscFunctionBegin; 2920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2921 PetscValidType(mat, 1); 2922 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2923 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2924 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2925 2926 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2927 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2928 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2929 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); 2930 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); 2931 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); 2932 MatCheckPreallocated(mat, 1); 2933 2934 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2935 PetscCall(VecLockReadPush(v1)); 2936 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2937 else { 2938 Vec w, z; 2939 PetscCall(VecDuplicate(v1, &w)); 2940 PetscCall(VecCopy(v1, w)); 2941 PetscCall(VecConjugate(w)); 2942 PetscCall(VecDuplicate(v3, &z)); 2943 PetscCall(MatMultTranspose(mat, w, z)); 2944 PetscCall(VecDestroy(&w)); 2945 PetscCall(VecConjugate(z)); 2946 if (v2 != v3) { 2947 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2948 } else { 2949 PetscCall(VecAXPY(v3, 1.0, z)); 2950 } 2951 PetscCall(VecDestroy(&z)); 2952 } 2953 PetscCall(VecLockReadPop(v1)); 2954 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2955 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2956 PetscFunctionReturn(PETSC_SUCCESS); 2957 } 2958 2959 /*@ 2960 MatGetFactorType - gets the type of factorization a matrix is 2961 2962 Not Collective 2963 2964 Input Parameter: 2965 . mat - the matrix 2966 2967 Output Parameter: 2968 . 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` 2969 2970 Level: intermediate 2971 2972 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2973 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2974 @*/ 2975 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2976 { 2977 PetscFunctionBegin; 2978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2979 PetscValidType(mat, 1); 2980 PetscAssertPointer(t, 2); 2981 *t = mat->factortype; 2982 PetscFunctionReturn(PETSC_SUCCESS); 2983 } 2984 2985 /*@ 2986 MatSetFactorType - sets the type of factorization a matrix is 2987 2988 Logically Collective 2989 2990 Input Parameters: 2991 + mat - the matrix 2992 - 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` 2993 2994 Level: intermediate 2995 2996 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2997 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2998 @*/ 2999 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3000 { 3001 PetscFunctionBegin; 3002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3003 PetscValidType(mat, 1); 3004 mat->factortype = t; 3005 PetscFunctionReturn(PETSC_SUCCESS); 3006 } 3007 3008 /*@ 3009 MatGetInfo - Returns information about matrix storage (number of 3010 nonzeros, memory, etc.). 3011 3012 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3013 3014 Input Parameters: 3015 + mat - the matrix 3016 - 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) 3017 3018 Output Parameter: 3019 . info - matrix information context 3020 3021 Options Database Key: 3022 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3023 3024 Level: intermediate 3025 3026 Notes: 3027 The `MatInfo` context contains a variety of matrix data, including 3028 number of nonzeros allocated and used, number of mallocs during 3029 matrix assembly, etc. Additional information for factored matrices 3030 is provided (such as the fill ratio, number of mallocs during 3031 factorization, etc.). 3032 3033 Example: 3034 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3035 data within the `MatInfo` context. For example, 3036 .vb 3037 MatInfo info; 3038 Mat A; 3039 double mal, nz_a, nz_u; 3040 3041 MatGetInfo(A, MAT_LOCAL, &info); 3042 mal = info.mallocs; 3043 nz_a = info.nz_allocated; 3044 .ve 3045 3046 Fortran Note: 3047 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3048 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3049 a complete list of parameter names. 3050 .vb 3051 MatInfo info(MAT_INFO_SIZE) 3052 double precision mal, nz_a 3053 Mat A 3054 integer ierr 3055 3056 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3057 mal = info(MAT_INFO_MALLOCS) 3058 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3059 .ve 3060 3061 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3062 @*/ 3063 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3064 { 3065 PetscFunctionBegin; 3066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3067 PetscValidType(mat, 1); 3068 PetscAssertPointer(info, 3); 3069 MatCheckPreallocated(mat, 1); 3070 PetscUseTypeMethod(mat, getinfo, flag, info); 3071 PetscFunctionReturn(PETSC_SUCCESS); 3072 } 3073 3074 /* 3075 This is used by external packages where it is not easy to get the info from the actual 3076 matrix factorization. 3077 */ 3078 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3079 { 3080 PetscFunctionBegin; 3081 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3082 PetscFunctionReturn(PETSC_SUCCESS); 3083 } 3084 3085 /*@ 3086 MatLUFactor - Performs in-place LU factorization of matrix. 3087 3088 Collective 3089 3090 Input Parameters: 3091 + mat - the matrix 3092 . row - row permutation 3093 . col - column permutation 3094 - info - options for factorization, includes 3095 .vb 3096 fill - expected fill as ratio of original fill. 3097 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3098 Run with the option -info to determine an optimal value to use 3099 .ve 3100 3101 Level: developer 3102 3103 Notes: 3104 Most users should employ the `KSP` interface for linear solvers 3105 instead of working directly with matrix algebra routines such as this. 3106 See, e.g., `KSPCreate()`. 3107 3108 This changes the state of the matrix to a factored matrix; it cannot be used 3109 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3110 3111 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3112 when not using `KSP`. 3113 3114 Developer Note: 3115 The Fortran interface is not autogenerated as the 3116 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3117 3118 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3119 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3120 @*/ 3121 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3122 { 3123 MatFactorInfo tinfo; 3124 3125 PetscFunctionBegin; 3126 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3127 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3128 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3129 if (info) PetscAssertPointer(info, 4); 3130 PetscValidType(mat, 1); 3131 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3132 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3133 MatCheckPreallocated(mat, 1); 3134 if (!info) { 3135 PetscCall(MatFactorInfoInitialize(&tinfo)); 3136 info = &tinfo; 3137 } 3138 3139 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3140 PetscUseTypeMethod(mat, lufactor, row, col, info); 3141 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3142 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3143 PetscFunctionReturn(PETSC_SUCCESS); 3144 } 3145 3146 /*@ 3147 MatILUFactor - Performs in-place ILU factorization of matrix. 3148 3149 Collective 3150 3151 Input Parameters: 3152 + mat - the matrix 3153 . row - row permutation 3154 . col - column permutation 3155 - info - structure containing 3156 .vb 3157 levels - number of levels of fill. 3158 expected fill - as ratio of original fill. 3159 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3160 missing diagonal entries) 3161 .ve 3162 3163 Level: developer 3164 3165 Notes: 3166 Most users should employ the `KSP` interface for linear solvers 3167 instead of working directly with matrix algebra routines such as this. 3168 See, e.g., `KSPCreate()`. 3169 3170 Probably really in-place only when level of fill is zero, otherwise allocates 3171 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3172 when not using `KSP`. 3173 3174 Developer Note: 3175 The Fortran interface is not autogenerated as the 3176 interface definition cannot be generated correctly [due to MatFactorInfo] 3177 3178 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3179 @*/ 3180 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3181 { 3182 PetscFunctionBegin; 3183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3184 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3185 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3186 PetscAssertPointer(info, 4); 3187 PetscValidType(mat, 1); 3188 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3189 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3191 MatCheckPreallocated(mat, 1); 3192 3193 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3194 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3195 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3196 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3197 PetscFunctionReturn(PETSC_SUCCESS); 3198 } 3199 3200 /*@ 3201 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3202 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3203 3204 Collective 3205 3206 Input Parameters: 3207 + fact - the factor matrix obtained with `MatGetFactor()` 3208 . mat - the matrix 3209 . row - the row permutation 3210 . col - the column permutation 3211 - info - options for factorization, includes 3212 .vb 3213 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3214 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3215 .ve 3216 3217 Level: developer 3218 3219 Notes: 3220 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3221 3222 Most users should employ the simplified `KSP` interface for linear solvers 3223 instead of working directly with matrix algebra routines such as this. 3224 See, e.g., `KSPCreate()`. 3225 3226 Developer Note: 3227 The Fortran interface is not autogenerated as the 3228 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3229 3230 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3231 @*/ 3232 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3233 { 3234 MatFactorInfo tinfo; 3235 3236 PetscFunctionBegin; 3237 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3239 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3240 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3241 if (info) PetscAssertPointer(info, 5); 3242 PetscValidType(fact, 1); 3243 PetscValidType(mat, 2); 3244 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3245 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3246 MatCheckPreallocated(mat, 2); 3247 if (!info) { 3248 PetscCall(MatFactorInfoInitialize(&tinfo)); 3249 info = &tinfo; 3250 } 3251 3252 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3253 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3254 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3255 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3256 PetscFunctionReturn(PETSC_SUCCESS); 3257 } 3258 3259 /*@ 3260 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3261 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3262 3263 Collective 3264 3265 Input Parameters: 3266 + fact - the factor matrix obtained with `MatGetFactor()` 3267 . mat - the matrix 3268 - info - options for factorization 3269 3270 Level: developer 3271 3272 Notes: 3273 See `MatLUFactor()` for in-place factorization. See 3274 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3275 3276 Most users should employ the `KSP` interface for linear solvers 3277 instead of working directly with matrix algebra routines such as this. 3278 See, e.g., `KSPCreate()`. 3279 3280 Developer Note: 3281 The Fortran interface is not autogenerated as the 3282 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3283 3284 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3285 @*/ 3286 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3287 { 3288 MatFactorInfo tinfo; 3289 3290 PetscFunctionBegin; 3291 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3293 PetscValidType(fact, 1); 3294 PetscValidType(mat, 2); 3295 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3296 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, 3297 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3298 3299 MatCheckPreallocated(mat, 2); 3300 if (!info) { 3301 PetscCall(MatFactorInfoInitialize(&tinfo)); 3302 info = &tinfo; 3303 } 3304 3305 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3306 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3307 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3308 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3309 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3310 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3311 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3312 PetscFunctionReturn(PETSC_SUCCESS); 3313 } 3314 3315 /*@ 3316 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3317 symmetric matrix. 3318 3319 Collective 3320 3321 Input Parameters: 3322 + mat - the matrix 3323 . perm - row and column permutations 3324 - info - expected fill as ratio of original fill 3325 3326 Level: developer 3327 3328 Notes: 3329 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3330 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3331 3332 Most users should employ the `KSP` interface for linear solvers 3333 instead of working directly with matrix algebra routines such as this. 3334 See, e.g., `KSPCreate()`. 3335 3336 Developer Note: 3337 The Fortran interface is not autogenerated as the 3338 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3339 3340 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3341 `MatGetOrdering()` 3342 @*/ 3343 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3344 { 3345 MatFactorInfo tinfo; 3346 3347 PetscFunctionBegin; 3348 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3349 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3350 if (info) PetscAssertPointer(info, 3); 3351 PetscValidType(mat, 1); 3352 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3353 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3354 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3355 MatCheckPreallocated(mat, 1); 3356 if (!info) { 3357 PetscCall(MatFactorInfoInitialize(&tinfo)); 3358 info = &tinfo; 3359 } 3360 3361 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3362 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3363 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3364 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3365 PetscFunctionReturn(PETSC_SUCCESS); 3366 } 3367 3368 /*@ 3369 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3370 of a symmetric matrix. 3371 3372 Collective 3373 3374 Input Parameters: 3375 + fact - the factor matrix obtained with `MatGetFactor()` 3376 . mat - the matrix 3377 . perm - row and column permutations 3378 - info - options for factorization, includes 3379 .vb 3380 fill - expected fill as ratio of original fill. 3381 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3382 Run with the option -info to determine an optimal value to use 3383 .ve 3384 3385 Level: developer 3386 3387 Notes: 3388 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3389 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3390 3391 Most users should employ the `KSP` interface for linear solvers 3392 instead of working directly with matrix algebra routines such as this. 3393 See, e.g., `KSPCreate()`. 3394 3395 Developer Note: 3396 The Fortran interface is not autogenerated as the 3397 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3398 3399 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3400 `MatGetOrdering()` 3401 @*/ 3402 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3403 { 3404 MatFactorInfo tinfo; 3405 3406 PetscFunctionBegin; 3407 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3409 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3410 if (info) PetscAssertPointer(info, 4); 3411 PetscValidType(fact, 1); 3412 PetscValidType(mat, 2); 3413 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3414 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3415 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3416 MatCheckPreallocated(mat, 2); 3417 if (!info) { 3418 PetscCall(MatFactorInfoInitialize(&tinfo)); 3419 info = &tinfo; 3420 } 3421 3422 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3423 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3424 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3425 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3426 PetscFunctionReturn(PETSC_SUCCESS); 3427 } 3428 3429 /*@ 3430 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3431 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3432 `MatCholeskyFactorSymbolic()`. 3433 3434 Collective 3435 3436 Input Parameters: 3437 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3438 . mat - the initial matrix that is to be factored 3439 - info - options for factorization 3440 3441 Level: developer 3442 3443 Note: 3444 Most users should employ the `KSP` interface for linear solvers 3445 instead of working directly with matrix algebra routines such as this. 3446 See, e.g., `KSPCreate()`. 3447 3448 Developer Note: 3449 The Fortran interface is not autogenerated as the 3450 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3451 3452 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3453 @*/ 3454 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3455 { 3456 MatFactorInfo tinfo; 3457 3458 PetscFunctionBegin; 3459 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3461 PetscValidType(fact, 1); 3462 PetscValidType(mat, 2); 3463 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3464 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, 3465 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3466 MatCheckPreallocated(mat, 2); 3467 if (!info) { 3468 PetscCall(MatFactorInfoInitialize(&tinfo)); 3469 info = &tinfo; 3470 } 3471 3472 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3473 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3474 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3475 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3476 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3477 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3478 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3479 PetscFunctionReturn(PETSC_SUCCESS); 3480 } 3481 3482 /*@ 3483 MatQRFactor - Performs in-place QR factorization of matrix. 3484 3485 Collective 3486 3487 Input Parameters: 3488 + mat - the matrix 3489 . col - column permutation 3490 - info - options for factorization, includes 3491 .vb 3492 fill - expected fill as ratio of original fill. 3493 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3494 Run with the option -info to determine an optimal value to use 3495 .ve 3496 3497 Level: developer 3498 3499 Notes: 3500 Most users should employ the `KSP` interface for linear solvers 3501 instead of working directly with matrix algebra routines such as this. 3502 See, e.g., `KSPCreate()`. 3503 3504 This changes the state of the matrix to a factored matrix; it cannot be used 3505 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3506 3507 Developer Note: 3508 The Fortran interface is not autogenerated as the 3509 interface definition cannot be generated correctly [due to MatFactorInfo] 3510 3511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3512 `MatSetUnfactored()` 3513 @*/ 3514 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3515 { 3516 PetscFunctionBegin; 3517 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3518 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3519 if (info) PetscAssertPointer(info, 3); 3520 PetscValidType(mat, 1); 3521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3523 MatCheckPreallocated(mat, 1); 3524 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3525 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3526 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3527 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3528 PetscFunctionReturn(PETSC_SUCCESS); 3529 } 3530 3531 /*@ 3532 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3533 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3534 3535 Collective 3536 3537 Input Parameters: 3538 + fact - the factor matrix obtained with `MatGetFactor()` 3539 . mat - the matrix 3540 . col - column permutation 3541 - info - options for factorization, includes 3542 .vb 3543 fill - expected fill as ratio of original fill. 3544 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3545 Run with the option -info to determine an optimal value to use 3546 .ve 3547 3548 Level: developer 3549 3550 Note: 3551 Most users should employ the `KSP` interface for linear solvers 3552 instead of working directly with matrix algebra routines such as this. 3553 See, e.g., `KSPCreate()`. 3554 3555 Developer Note: 3556 The Fortran interface is not autogenerated as the 3557 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3558 3559 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3560 @*/ 3561 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3562 { 3563 MatFactorInfo tinfo; 3564 3565 PetscFunctionBegin; 3566 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3568 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3569 if (info) PetscAssertPointer(info, 4); 3570 PetscValidType(fact, 1); 3571 PetscValidType(mat, 2); 3572 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3573 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3574 MatCheckPreallocated(mat, 2); 3575 if (!info) { 3576 PetscCall(MatFactorInfoInitialize(&tinfo)); 3577 info = &tinfo; 3578 } 3579 3580 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3581 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3582 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3583 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3584 PetscFunctionReturn(PETSC_SUCCESS); 3585 } 3586 3587 /*@ 3588 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3589 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3590 3591 Collective 3592 3593 Input Parameters: 3594 + fact - the factor matrix obtained with `MatGetFactor()` 3595 . mat - the matrix 3596 - info - options for factorization 3597 3598 Level: developer 3599 3600 Notes: 3601 See `MatQRFactor()` for in-place factorization. 3602 3603 Most users should employ the `KSP` interface for linear solvers 3604 instead of working directly with matrix algebra routines such as this. 3605 See, e.g., `KSPCreate()`. 3606 3607 Developer Note: 3608 The Fortran interface is not autogenerated as the 3609 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3610 3611 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3612 @*/ 3613 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3614 { 3615 MatFactorInfo tinfo; 3616 3617 PetscFunctionBegin; 3618 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3619 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3620 PetscValidType(fact, 1); 3621 PetscValidType(mat, 2); 3622 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3623 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, 3624 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3625 3626 MatCheckPreallocated(mat, 2); 3627 if (!info) { 3628 PetscCall(MatFactorInfoInitialize(&tinfo)); 3629 info = &tinfo; 3630 } 3631 3632 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3633 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3634 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3635 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3636 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3637 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3638 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3639 PetscFunctionReturn(PETSC_SUCCESS); 3640 } 3641 3642 /*@ 3643 MatSolve - Solves $A x = b$, given a factored matrix. 3644 3645 Neighbor-wise Collective 3646 3647 Input Parameters: 3648 + mat - the factored matrix 3649 - b - the right-hand-side vector 3650 3651 Output Parameter: 3652 . x - the result vector 3653 3654 Level: developer 3655 3656 Notes: 3657 The vectors `b` and `x` cannot be the same. I.e., one cannot 3658 call `MatSolve`(A,x,x). 3659 3660 Most users should employ the `KSP` interface for linear solvers 3661 instead of working directly with matrix algebra routines such as this. 3662 See, e.g., `KSPCreate()`. 3663 3664 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3665 @*/ 3666 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3667 { 3668 PetscFunctionBegin; 3669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3670 PetscValidType(mat, 1); 3671 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3672 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3673 PetscCheckSameComm(mat, 1, b, 2); 3674 PetscCheckSameComm(mat, 1, x, 3); 3675 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3676 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); 3677 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); 3678 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); 3679 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3680 MatCheckPreallocated(mat, 1); 3681 3682 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3683 PetscCall(VecFlag(x, mat->factorerrortype)); 3684 if (mat->factorerrortype) { 3685 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3686 } else PetscUseTypeMethod(mat, solve, b, x); 3687 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3688 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3689 PetscFunctionReturn(PETSC_SUCCESS); 3690 } 3691 3692 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3693 { 3694 Vec b, x; 3695 PetscInt N, i; 3696 PetscErrorCode (*f)(Mat, Vec, Vec); 3697 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3698 3699 PetscFunctionBegin; 3700 if (A->factorerrortype) { 3701 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3702 PetscCall(MatSetInf(X)); 3703 PetscFunctionReturn(PETSC_SUCCESS); 3704 } 3705 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3706 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3707 PetscCall(MatBoundToCPU(A, &Abound)); 3708 if (!Abound) { 3709 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3710 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3711 } 3712 #if PetscDefined(HAVE_CUDA) 3713 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3714 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3715 #elif PetscDefined(HAVE_HIP) 3716 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3717 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3718 #endif 3719 PetscCall(MatGetSize(B, NULL, &N)); 3720 for (i = 0; i < N; i++) { 3721 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3722 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3723 PetscCall((*f)(A, b, x)); 3724 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3725 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3726 } 3727 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3728 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3729 PetscFunctionReturn(PETSC_SUCCESS); 3730 } 3731 3732 /*@ 3733 MatMatSolve - Solves $A X = B$, given a factored matrix. 3734 3735 Neighbor-wise Collective 3736 3737 Input Parameters: 3738 + A - the factored matrix 3739 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3740 3741 Output Parameter: 3742 . X - the result matrix (dense matrix) 3743 3744 Level: developer 3745 3746 Note: 3747 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3748 otherwise, `B` and `X` cannot be the same. 3749 3750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3751 @*/ 3752 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3753 { 3754 PetscFunctionBegin; 3755 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3756 PetscValidType(A, 1); 3757 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3758 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3759 PetscCheckSameComm(A, 1, B, 2); 3760 PetscCheckSameComm(A, 1, X, 3); 3761 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); 3762 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); 3763 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"); 3764 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3765 MatCheckPreallocated(A, 1); 3766 3767 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3768 if (!A->ops->matsolve) { 3769 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3770 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3771 } else PetscUseTypeMethod(A, matsolve, B, X); 3772 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3773 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3774 PetscFunctionReturn(PETSC_SUCCESS); 3775 } 3776 3777 /*@ 3778 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3779 3780 Neighbor-wise Collective 3781 3782 Input Parameters: 3783 + A - the factored matrix 3784 - B - the right-hand-side matrix (`MATDENSE` matrix) 3785 3786 Output Parameter: 3787 . X - the result matrix (dense matrix) 3788 3789 Level: developer 3790 3791 Note: 3792 The matrices `B` and `X` cannot be the same. I.e., one cannot 3793 call `MatMatSolveTranspose`(A,X,X). 3794 3795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3796 @*/ 3797 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3798 { 3799 PetscFunctionBegin; 3800 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3801 PetscValidType(A, 1); 3802 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3803 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3804 PetscCheckSameComm(A, 1, B, 2); 3805 PetscCheckSameComm(A, 1, X, 3); 3806 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3807 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); 3808 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); 3809 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); 3810 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"); 3811 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3812 MatCheckPreallocated(A, 1); 3813 3814 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3815 if (!A->ops->matsolvetranspose) { 3816 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3817 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3818 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3819 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3820 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3821 PetscFunctionReturn(PETSC_SUCCESS); 3822 } 3823 3824 /*@ 3825 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3826 3827 Neighbor-wise Collective 3828 3829 Input Parameters: 3830 + A - the factored matrix 3831 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3832 3833 Output Parameter: 3834 . X - the result matrix (dense matrix) 3835 3836 Level: developer 3837 3838 Note: 3839 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 3840 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3841 3842 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3843 @*/ 3844 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3845 { 3846 PetscFunctionBegin; 3847 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3848 PetscValidType(A, 1); 3849 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3850 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3851 PetscCheckSameComm(A, 1, Bt, 2); 3852 PetscCheckSameComm(A, 1, X, 3); 3853 3854 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3855 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); 3856 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); 3857 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"); 3858 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3859 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3860 MatCheckPreallocated(A, 1); 3861 3862 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3863 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3864 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3865 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3866 PetscFunctionReturn(PETSC_SUCCESS); 3867 } 3868 3869 /*@ 3870 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3871 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3872 3873 Neighbor-wise Collective 3874 3875 Input Parameters: 3876 + mat - the factored matrix 3877 - b - the right-hand-side vector 3878 3879 Output Parameter: 3880 . x - the result vector 3881 3882 Level: developer 3883 3884 Notes: 3885 `MatSolve()` should be used for most applications, as it performs 3886 a forward solve followed by a backward solve. 3887 3888 The vectors `b` and `x` cannot be the same, i.e., one cannot 3889 call `MatForwardSolve`(A,x,x). 3890 3891 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3892 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3893 `MatForwardSolve()` solves $U^T*D y = b$, and 3894 `MatBackwardSolve()` solves $U x = y$. 3895 Thus they do not provide a symmetric preconditioner. 3896 3897 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3898 @*/ 3899 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3900 { 3901 PetscFunctionBegin; 3902 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3903 PetscValidType(mat, 1); 3904 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3905 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3906 PetscCheckSameComm(mat, 1, b, 2); 3907 PetscCheckSameComm(mat, 1, x, 3); 3908 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3909 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); 3910 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); 3911 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); 3912 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3913 MatCheckPreallocated(mat, 1); 3914 3915 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3916 PetscUseTypeMethod(mat, forwardsolve, b, x); 3917 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3918 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3919 PetscFunctionReturn(PETSC_SUCCESS); 3920 } 3921 3922 /*@ 3923 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3924 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3925 3926 Neighbor-wise Collective 3927 3928 Input Parameters: 3929 + mat - the factored matrix 3930 - b - the right-hand-side vector 3931 3932 Output Parameter: 3933 . x - the result vector 3934 3935 Level: developer 3936 3937 Notes: 3938 `MatSolve()` should be used for most applications, as it performs 3939 a forward solve followed by a backward solve. 3940 3941 The vectors `b` and `x` cannot be the same. I.e., one cannot 3942 call `MatBackwardSolve`(A,x,x). 3943 3944 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3945 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3946 `MatForwardSolve()` solves $U^T*D y = b$, and 3947 `MatBackwardSolve()` solves $U x = y$. 3948 Thus they do not provide a symmetric preconditioner. 3949 3950 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3951 @*/ 3952 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3953 { 3954 PetscFunctionBegin; 3955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3956 PetscValidType(mat, 1); 3957 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3958 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3959 PetscCheckSameComm(mat, 1, b, 2); 3960 PetscCheckSameComm(mat, 1, x, 3); 3961 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3962 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); 3963 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); 3964 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); 3965 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3966 MatCheckPreallocated(mat, 1); 3967 3968 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3969 PetscUseTypeMethod(mat, backwardsolve, b, x); 3970 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3971 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3972 PetscFunctionReturn(PETSC_SUCCESS); 3973 } 3974 3975 /*@ 3976 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3977 3978 Neighbor-wise Collective 3979 3980 Input Parameters: 3981 + mat - the factored matrix 3982 . b - the right-hand-side vector 3983 - y - the vector to be added to 3984 3985 Output Parameter: 3986 . x - the result vector 3987 3988 Level: developer 3989 3990 Note: 3991 The vectors `b` and `x` cannot be the same. I.e., one cannot 3992 call `MatSolveAdd`(A,x,y,x). 3993 3994 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3995 @*/ 3996 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3997 { 3998 PetscScalar one = 1.0; 3999 Vec tmp; 4000 4001 PetscFunctionBegin; 4002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4003 PetscValidType(mat, 1); 4004 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4005 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4006 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4007 PetscCheckSameComm(mat, 1, b, 2); 4008 PetscCheckSameComm(mat, 1, y, 3); 4009 PetscCheckSameComm(mat, 1, x, 4); 4010 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4011 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); 4012 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); 4013 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); 4014 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); 4015 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); 4016 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4017 MatCheckPreallocated(mat, 1); 4018 4019 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4020 PetscCall(VecFlag(x, mat->factorerrortype)); 4021 if (mat->factorerrortype) { 4022 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4023 } else if (mat->ops->solveadd) { 4024 PetscUseTypeMethod(mat, solveadd, b, y, x); 4025 } else { 4026 /* do the solve then the add manually */ 4027 if (x != y) { 4028 PetscCall(MatSolve(mat, b, x)); 4029 PetscCall(VecAXPY(x, one, y)); 4030 } else { 4031 PetscCall(VecDuplicate(x, &tmp)); 4032 PetscCall(VecCopy(x, tmp)); 4033 PetscCall(MatSolve(mat, b, x)); 4034 PetscCall(VecAXPY(x, one, tmp)); 4035 PetscCall(VecDestroy(&tmp)); 4036 } 4037 } 4038 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4039 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4040 PetscFunctionReturn(PETSC_SUCCESS); 4041 } 4042 4043 /*@ 4044 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4045 4046 Neighbor-wise Collective 4047 4048 Input Parameters: 4049 + mat - the factored matrix 4050 - b - the right-hand-side vector 4051 4052 Output Parameter: 4053 . x - the result vector 4054 4055 Level: developer 4056 4057 Notes: 4058 The vectors `b` and `x` cannot be the same. I.e., one cannot 4059 call `MatSolveTranspose`(A,x,x). 4060 4061 Most users should employ the `KSP` interface for linear solvers 4062 instead of working directly with matrix algebra routines such as this. 4063 See, e.g., `KSPCreate()`. 4064 4065 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4066 @*/ 4067 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4068 { 4069 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4070 4071 PetscFunctionBegin; 4072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4073 PetscValidType(mat, 1); 4074 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4075 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4076 PetscCheckSameComm(mat, 1, b, 2); 4077 PetscCheckSameComm(mat, 1, x, 3); 4078 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4079 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); 4080 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); 4081 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4082 MatCheckPreallocated(mat, 1); 4083 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4084 PetscCall(VecFlag(x, mat->factorerrortype)); 4085 if (mat->factorerrortype) { 4086 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4087 } else { 4088 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4089 PetscCall((*f)(mat, b, x)); 4090 } 4091 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4092 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4093 PetscFunctionReturn(PETSC_SUCCESS); 4094 } 4095 4096 /*@ 4097 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4098 factored matrix. 4099 4100 Neighbor-wise Collective 4101 4102 Input Parameters: 4103 + mat - the factored matrix 4104 . b - the right-hand-side vector 4105 - y - the vector to be added to 4106 4107 Output Parameter: 4108 . x - the result vector 4109 4110 Level: developer 4111 4112 Note: 4113 The vectors `b` and `x` cannot be the same. I.e., one cannot 4114 call `MatSolveTransposeAdd`(A,x,y,x). 4115 4116 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4117 @*/ 4118 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4119 { 4120 PetscScalar one = 1.0; 4121 Vec tmp; 4122 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4123 4124 PetscFunctionBegin; 4125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4126 PetscValidType(mat, 1); 4127 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4128 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4129 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4130 PetscCheckSameComm(mat, 1, b, 2); 4131 PetscCheckSameComm(mat, 1, y, 3); 4132 PetscCheckSameComm(mat, 1, x, 4); 4133 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4134 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); 4135 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); 4136 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); 4137 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); 4138 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4139 MatCheckPreallocated(mat, 1); 4140 4141 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4142 PetscCall(VecFlag(x, mat->factorerrortype)); 4143 if (mat->factorerrortype) { 4144 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4145 } else if (f) { 4146 PetscCall((*f)(mat, b, y, x)); 4147 } else { 4148 /* do the solve then the add manually */ 4149 if (x != y) { 4150 PetscCall(MatSolveTranspose(mat, b, x)); 4151 PetscCall(VecAXPY(x, one, y)); 4152 } else { 4153 PetscCall(VecDuplicate(x, &tmp)); 4154 PetscCall(VecCopy(x, tmp)); 4155 PetscCall(MatSolveTranspose(mat, b, x)); 4156 PetscCall(VecAXPY(x, one, tmp)); 4157 PetscCall(VecDestroy(&tmp)); 4158 } 4159 } 4160 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4161 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4162 PetscFunctionReturn(PETSC_SUCCESS); 4163 } 4164 4165 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4166 /*@ 4167 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4168 4169 Neighbor-wise Collective 4170 4171 Input Parameters: 4172 + mat - the matrix 4173 . b - the right-hand side 4174 . omega - the relaxation factor 4175 . flag - flag indicating the type of SOR (see below) 4176 . shift - diagonal shift 4177 . its - the number of iterations 4178 - lits - the number of local iterations 4179 4180 Output Parameter: 4181 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4182 4183 SOR Flags: 4184 + `SOR_FORWARD_SWEEP` - forward SOR 4185 . `SOR_BACKWARD_SWEEP` - backward SOR 4186 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4187 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4188 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4189 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4190 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4191 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4192 upper/lower triangular part of matrix to 4193 vector (with omega) 4194 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4195 4196 Level: developer 4197 4198 Notes: 4199 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4200 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4201 on each processor. 4202 4203 Application programmers will not generally use `MatSOR()` directly, 4204 but instead will employ the `KSP`/`PC` interface. 4205 4206 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4207 4208 Most users should employ the `KSP` interface for linear solvers 4209 instead of working directly with matrix algebra routines such as this. 4210 See, e.g., `KSPCreate()`. 4211 4212 Vectors `x` and `b` CANNOT be the same 4213 4214 The flags are implemented as bitwise inclusive or operations. 4215 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4216 to specify a zero initial guess for SSOR. 4217 4218 Developer Note: 4219 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4220 4221 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4222 @*/ 4223 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4224 { 4225 PetscFunctionBegin; 4226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4227 PetscValidType(mat, 1); 4228 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4229 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4230 PetscCheckSameComm(mat, 1, b, 2); 4231 PetscCheckSameComm(mat, 1, x, 8); 4232 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4233 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4234 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); 4235 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); 4236 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); 4237 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4238 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4239 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4240 4241 MatCheckPreallocated(mat, 1); 4242 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4243 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4244 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4245 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4246 PetscFunctionReturn(PETSC_SUCCESS); 4247 } 4248 4249 /* 4250 Default matrix copy routine. 4251 */ 4252 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4253 { 4254 PetscInt i, rstart = 0, rend = 0, nz; 4255 const PetscInt *cwork; 4256 const PetscScalar *vwork; 4257 4258 PetscFunctionBegin; 4259 if (B->assembled) PetscCall(MatZeroEntries(B)); 4260 if (str == SAME_NONZERO_PATTERN) { 4261 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4262 for (i = rstart; i < rend; i++) { 4263 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4264 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4265 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4266 } 4267 } else { 4268 PetscCall(MatAYPX(B, 0.0, A, str)); 4269 } 4270 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4271 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4272 PetscFunctionReturn(PETSC_SUCCESS); 4273 } 4274 4275 /*@ 4276 MatCopy - Copies a matrix to another matrix. 4277 4278 Collective 4279 4280 Input Parameters: 4281 + A - the matrix 4282 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4283 4284 Output Parameter: 4285 . B - where the copy is put 4286 4287 Level: intermediate 4288 4289 Notes: 4290 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4291 4292 `MatCopy()` copies the matrix entries of a matrix to another existing 4293 matrix (after first zeroing the second matrix). A related routine is 4294 `MatConvert()`, which first creates a new matrix and then copies the data. 4295 4296 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4297 @*/ 4298 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4299 { 4300 PetscInt i; 4301 4302 PetscFunctionBegin; 4303 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4304 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4305 PetscValidType(A, 1); 4306 PetscValidType(B, 2); 4307 PetscCheckSameComm(A, 1, B, 2); 4308 MatCheckPreallocated(B, 2); 4309 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4310 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4311 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, 4312 A->cmap->N, B->cmap->N); 4313 MatCheckPreallocated(A, 1); 4314 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4315 4316 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4317 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4318 else PetscCall(MatCopy_Basic(A, B, str)); 4319 4320 B->stencil.dim = A->stencil.dim; 4321 B->stencil.noc = A->stencil.noc; 4322 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4323 B->stencil.dims[i] = A->stencil.dims[i]; 4324 B->stencil.starts[i] = A->stencil.starts[i]; 4325 } 4326 4327 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4328 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4329 PetscFunctionReturn(PETSC_SUCCESS); 4330 } 4331 4332 /*@ 4333 MatConvert - Converts a matrix to another matrix, either of the same 4334 or different type. 4335 4336 Collective 4337 4338 Input Parameters: 4339 + mat - the matrix 4340 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4341 same type as the original matrix. 4342 - reuse - denotes if the destination matrix is to be created or reused. 4343 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 4344 `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). 4345 4346 Output Parameter: 4347 . M - pointer to place new matrix 4348 4349 Level: intermediate 4350 4351 Notes: 4352 `MatConvert()` first creates a new matrix and then copies the data from 4353 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4354 entries of one matrix to another already existing matrix context. 4355 4356 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4357 the MPI communicator of the generated matrix is always the same as the communicator 4358 of the input matrix. 4359 4360 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4361 @*/ 4362 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4363 { 4364 PetscBool sametype, issame, flg; 4365 PetscBool3 issymmetric, ishermitian; 4366 char convname[256], mtype[256]; 4367 Mat B; 4368 4369 PetscFunctionBegin; 4370 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4371 PetscValidType(mat, 1); 4372 PetscAssertPointer(M, 4); 4373 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4374 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4375 MatCheckPreallocated(mat, 1); 4376 4377 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4378 if (flg) newtype = mtype; 4379 4380 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4381 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4382 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4383 if (reuse == MAT_REUSE_MATRIX) { 4384 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4385 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4386 } 4387 4388 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4389 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4390 PetscFunctionReturn(PETSC_SUCCESS); 4391 } 4392 4393 /* Cache Mat options because some converters use MatHeaderReplace */ 4394 issymmetric = mat->symmetric; 4395 ishermitian = mat->hermitian; 4396 4397 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4398 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4399 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4400 } else { 4401 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4402 const char *prefix[3] = {"seq", "mpi", ""}; 4403 PetscInt i; 4404 /* 4405 Order of precedence: 4406 0) See if newtype is a superclass of the current matrix. 4407 1) See if a specialized converter is known to the current matrix. 4408 2) See if a specialized converter is known to the desired matrix class. 4409 3) See if a good general converter is registered for the desired class 4410 (as of 6/27/03 only MATMPIADJ falls into this category). 4411 4) See if a good general converter is known for the current matrix. 4412 5) Use a really basic converter. 4413 */ 4414 4415 /* 0) See if newtype is a superclass of the current matrix. 4416 i.e mat is mpiaij and newtype is aij */ 4417 for (i = 0; i < 2; i++) { 4418 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4419 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4420 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4421 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4422 if (flg) { 4423 if (reuse == MAT_INPLACE_MATRIX) { 4424 PetscCall(PetscInfo(mat, "Early return\n")); 4425 PetscFunctionReturn(PETSC_SUCCESS); 4426 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4427 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4428 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4429 PetscFunctionReturn(PETSC_SUCCESS); 4430 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4431 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4432 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4433 PetscFunctionReturn(PETSC_SUCCESS); 4434 } 4435 } 4436 } 4437 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4438 for (i = 0; i < 3; i++) { 4439 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4440 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4441 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4443 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4444 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4445 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4446 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4447 if (conv) goto foundconv; 4448 } 4449 4450 /* 2) See if a specialized converter is known to the desired matrix class. */ 4451 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4452 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4453 PetscCall(MatSetType(B, newtype)); 4454 for (i = 0; i < 3; i++) { 4455 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4456 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4457 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4458 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4459 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4460 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4461 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4462 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4463 if (conv) { 4464 PetscCall(MatDestroy(&B)); 4465 goto foundconv; 4466 } 4467 } 4468 4469 /* 3) See if a good general converter is registered for the desired class */ 4470 conv = B->ops->convertfrom; 4471 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4472 PetscCall(MatDestroy(&B)); 4473 if (conv) goto foundconv; 4474 4475 /* 4) See if a good general converter is known for the current matrix */ 4476 if (mat->ops->convert) conv = mat->ops->convert; 4477 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4478 if (conv) goto foundconv; 4479 4480 /* 5) Use a really basic converter. */ 4481 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4482 conv = MatConvert_Basic; 4483 4484 foundconv: 4485 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4486 PetscCall((*conv)(mat, newtype, reuse, M)); 4487 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4488 /* the block sizes must be same if the mappings are copied over */ 4489 (*M)->rmap->bs = mat->rmap->bs; 4490 (*M)->cmap->bs = mat->cmap->bs; 4491 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4492 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4493 (*M)->rmap->mapping = mat->rmap->mapping; 4494 (*M)->cmap->mapping = mat->cmap->mapping; 4495 } 4496 (*M)->stencil.dim = mat->stencil.dim; 4497 (*M)->stencil.noc = mat->stencil.noc; 4498 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4499 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4500 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4501 } 4502 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4503 } 4504 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4505 4506 /* Copy Mat options */ 4507 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4508 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4509 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4510 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4511 PetscFunctionReturn(PETSC_SUCCESS); 4512 } 4513 4514 /*@ 4515 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4516 4517 Not Collective 4518 4519 Input Parameter: 4520 . mat - the matrix, must be a factored matrix 4521 4522 Output Parameter: 4523 . type - the string name of the package (do not free this string) 4524 4525 Level: intermediate 4526 4527 Fortran Note: 4528 Pass in an empty string that is long enough and the package name will be copied into it. 4529 4530 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4531 @*/ 4532 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4533 { 4534 PetscErrorCode (*conv)(Mat, MatSolverType *); 4535 4536 PetscFunctionBegin; 4537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4538 PetscValidType(mat, 1); 4539 PetscAssertPointer(type, 2); 4540 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4541 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4542 if (conv) PetscCall((*conv)(mat, type)); 4543 else *type = MATSOLVERPETSC; 4544 PetscFunctionReturn(PETSC_SUCCESS); 4545 } 4546 4547 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4548 struct _MatSolverTypeForSpecifcType { 4549 MatType mtype; 4550 /* no entry for MAT_FACTOR_NONE */ 4551 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4552 MatSolverTypeForSpecifcType next; 4553 }; 4554 4555 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4556 struct _MatSolverTypeHolder { 4557 char *name; 4558 MatSolverTypeForSpecifcType handlers; 4559 MatSolverTypeHolder next; 4560 }; 4561 4562 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4563 4564 /*@C 4565 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4566 4567 Logically Collective, No Fortran Support 4568 4569 Input Parameters: 4570 + package - name of the package, for example petsc or superlu 4571 . mtype - the matrix type that works with this package 4572 . ftype - the type of factorization supported by the package 4573 - createfactor - routine that will create the factored matrix ready to be used 4574 4575 Level: developer 4576 4577 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4578 `MatGetFactor()` 4579 @*/ 4580 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4581 { 4582 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4583 PetscBool flg; 4584 MatSolverTypeForSpecifcType inext, iprev = NULL; 4585 4586 PetscFunctionBegin; 4587 PetscCall(MatInitializePackage()); 4588 if (!next) { 4589 PetscCall(PetscNew(&MatSolverTypeHolders)); 4590 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4591 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4592 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4593 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4594 PetscFunctionReturn(PETSC_SUCCESS); 4595 } 4596 while (next) { 4597 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4598 if (flg) { 4599 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4600 inext = next->handlers; 4601 while (inext) { 4602 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4603 if (flg) { 4604 inext->createfactor[(int)ftype - 1] = createfactor; 4605 PetscFunctionReturn(PETSC_SUCCESS); 4606 } 4607 iprev = inext; 4608 inext = inext->next; 4609 } 4610 PetscCall(PetscNew(&iprev->next)); 4611 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4612 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4613 PetscFunctionReturn(PETSC_SUCCESS); 4614 } 4615 prev = next; 4616 next = next->next; 4617 } 4618 PetscCall(PetscNew(&prev->next)); 4619 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4620 PetscCall(PetscNew(&prev->next->handlers)); 4621 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4622 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4623 PetscFunctionReturn(PETSC_SUCCESS); 4624 } 4625 4626 /*@C 4627 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4628 4629 Input Parameters: 4630 + 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 4631 . ftype - the type of factorization supported by the type 4632 - mtype - the matrix type that works with this type 4633 4634 Output Parameters: 4635 + foundtype - `PETSC_TRUE` if the type was registered 4636 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4637 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4638 4639 Calling sequence of `createfactor`: 4640 + A - the matrix providing the factor matrix 4641 . ftype - the `MatFactorType` of the factor requested 4642 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4643 4644 Level: developer 4645 4646 Note: 4647 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4648 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4649 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4650 4651 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4652 `MatInitializePackage()` 4653 @*/ 4654 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4655 { 4656 MatSolverTypeHolder next = MatSolverTypeHolders; 4657 PetscBool flg; 4658 MatSolverTypeForSpecifcType inext; 4659 4660 PetscFunctionBegin; 4661 if (foundtype) *foundtype = PETSC_FALSE; 4662 if (foundmtype) *foundmtype = PETSC_FALSE; 4663 if (createfactor) *createfactor = NULL; 4664 4665 if (type) { 4666 while (next) { 4667 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4668 if (flg) { 4669 if (foundtype) *foundtype = PETSC_TRUE; 4670 inext = next->handlers; 4671 while (inext) { 4672 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4673 if (flg) { 4674 if (foundmtype) *foundmtype = PETSC_TRUE; 4675 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4676 PetscFunctionReturn(PETSC_SUCCESS); 4677 } 4678 inext = inext->next; 4679 } 4680 } 4681 next = next->next; 4682 } 4683 } else { 4684 while (next) { 4685 inext = next->handlers; 4686 while (inext) { 4687 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4688 if (flg && inext->createfactor[(int)ftype - 1]) { 4689 if (foundtype) *foundtype = PETSC_TRUE; 4690 if (foundmtype) *foundmtype = PETSC_TRUE; 4691 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4692 PetscFunctionReturn(PETSC_SUCCESS); 4693 } 4694 inext = inext->next; 4695 } 4696 next = next->next; 4697 } 4698 /* try with base classes inext->mtype */ 4699 next = MatSolverTypeHolders; 4700 while (next) { 4701 inext = next->handlers; 4702 while (inext) { 4703 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4704 if (flg && inext->createfactor[(int)ftype - 1]) { 4705 if (foundtype) *foundtype = PETSC_TRUE; 4706 if (foundmtype) *foundmtype = PETSC_TRUE; 4707 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4708 PetscFunctionReturn(PETSC_SUCCESS); 4709 } 4710 inext = inext->next; 4711 } 4712 next = next->next; 4713 } 4714 } 4715 PetscFunctionReturn(PETSC_SUCCESS); 4716 } 4717 4718 PetscErrorCode MatSolverTypeDestroy(void) 4719 { 4720 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4721 MatSolverTypeForSpecifcType inext, iprev; 4722 4723 PetscFunctionBegin; 4724 while (next) { 4725 PetscCall(PetscFree(next->name)); 4726 inext = next->handlers; 4727 while (inext) { 4728 PetscCall(PetscFree(inext->mtype)); 4729 iprev = inext; 4730 inext = inext->next; 4731 PetscCall(PetscFree(iprev)); 4732 } 4733 prev = next; 4734 next = next->next; 4735 PetscCall(PetscFree(prev)); 4736 } 4737 MatSolverTypeHolders = NULL; 4738 PetscFunctionReturn(PETSC_SUCCESS); 4739 } 4740 4741 /*@ 4742 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4743 4744 Logically Collective 4745 4746 Input Parameter: 4747 . mat - the matrix 4748 4749 Output Parameter: 4750 . flg - `PETSC_TRUE` if uses the ordering 4751 4752 Level: developer 4753 4754 Note: 4755 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4756 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4757 4758 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4759 @*/ 4760 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4761 { 4762 PetscFunctionBegin; 4763 *flg = mat->canuseordering; 4764 PetscFunctionReturn(PETSC_SUCCESS); 4765 } 4766 4767 /*@ 4768 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4769 4770 Logically Collective 4771 4772 Input Parameters: 4773 + mat - the matrix obtained with `MatGetFactor()` 4774 - ftype - the factorization type to be used 4775 4776 Output Parameter: 4777 . otype - the preferred ordering type 4778 4779 Level: developer 4780 4781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4782 @*/ 4783 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4784 { 4785 PetscFunctionBegin; 4786 *otype = mat->preferredordering[ftype]; 4787 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4788 PetscFunctionReturn(PETSC_SUCCESS); 4789 } 4790 4791 /*@ 4792 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4793 4794 Collective 4795 4796 Input Parameters: 4797 + mat - the matrix 4798 . 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 4799 the other criteria is returned 4800 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4801 4802 Output Parameter: 4803 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4804 4805 Options Database Keys: 4806 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4807 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4808 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4809 4810 Level: intermediate 4811 4812 Notes: 4813 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4814 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4815 4816 Users usually access the factorization solvers via `KSP` 4817 4818 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4819 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 4820 4821 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4822 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4823 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4824 4825 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4826 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4827 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4828 4829 Developer Note: 4830 This should actually be called `MatCreateFactor()` since it creates a new factor object 4831 4832 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4833 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4834 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4835 @*/ 4836 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4837 { 4838 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4839 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4840 4841 PetscFunctionBegin; 4842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4843 PetscValidType(mat, 1); 4844 4845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4846 MatCheckPreallocated(mat, 1); 4847 4848 PetscCall(MatIsShell(mat, &shell)); 4849 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4850 if (hasop) { 4851 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4852 PetscFunctionReturn(PETSC_SUCCESS); 4853 } 4854 4855 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4856 if (!foundtype) { 4857 if (type) { 4858 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], 4859 ((PetscObject)mat)->type_name, type); 4860 } else { 4861 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); 4862 } 4863 } 4864 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4865 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); 4866 4867 PetscCall((*conv)(mat, ftype, f)); 4868 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4869 PetscFunctionReturn(PETSC_SUCCESS); 4870 } 4871 4872 /*@ 4873 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4874 4875 Not Collective 4876 4877 Input Parameters: 4878 + mat - the matrix 4879 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4880 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4881 4882 Output Parameter: 4883 . flg - PETSC_TRUE if the factorization is available 4884 4885 Level: intermediate 4886 4887 Notes: 4888 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4889 such as pastix, superlu, mumps etc. 4890 4891 PETSc must have been ./configure to use the external solver, using the option --download-package 4892 4893 Developer Note: 4894 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4895 4896 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4897 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4898 @*/ 4899 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4900 { 4901 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4902 4903 PetscFunctionBegin; 4904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4905 PetscAssertPointer(flg, 4); 4906 4907 *flg = PETSC_FALSE; 4908 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4909 4910 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4911 MatCheckPreallocated(mat, 1); 4912 4913 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4914 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4915 PetscFunctionReturn(PETSC_SUCCESS); 4916 } 4917 4918 /*@ 4919 MatDuplicate - Duplicates a matrix including the non-zero structure. 4920 4921 Collective 4922 4923 Input Parameters: 4924 + mat - the matrix 4925 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4926 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4927 4928 Output Parameter: 4929 . M - pointer to place new matrix 4930 4931 Level: intermediate 4932 4933 Notes: 4934 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4935 4936 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4937 4938 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. 4939 4940 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4941 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4942 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4943 4944 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4945 @*/ 4946 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4947 { 4948 Mat B; 4949 VecType vtype; 4950 PetscInt i; 4951 PetscObject dm, container_h, container_d; 4952 void (*viewf)(void); 4953 4954 PetscFunctionBegin; 4955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4956 PetscValidType(mat, 1); 4957 PetscAssertPointer(M, 3); 4958 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4959 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4960 MatCheckPreallocated(mat, 1); 4961 4962 *M = NULL; 4963 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4964 PetscUseTypeMethod(mat, duplicate, op, M); 4965 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4966 B = *M; 4967 4968 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4969 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4970 PetscCall(MatGetVecType(mat, &vtype)); 4971 PetscCall(MatSetVecType(B, vtype)); 4972 4973 B->stencil.dim = mat->stencil.dim; 4974 B->stencil.noc = mat->stencil.noc; 4975 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4976 B->stencil.dims[i] = mat->stencil.dims[i]; 4977 B->stencil.starts[i] = mat->stencil.starts[i]; 4978 } 4979 4980 B->nooffproczerorows = mat->nooffproczerorows; 4981 B->nooffprocentries = mat->nooffprocentries; 4982 4983 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4984 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4985 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4986 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4987 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4988 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4989 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4990 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4991 PetscFunctionReturn(PETSC_SUCCESS); 4992 } 4993 4994 /*@ 4995 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4996 4997 Logically Collective 4998 4999 Input Parameter: 5000 . mat - the matrix 5001 5002 Output Parameter: 5003 . v - the diagonal of the matrix 5004 5005 Level: intermediate 5006 5007 Note: 5008 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5009 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5010 is larger than `ndiag`, the values of the remaining entries are unspecified. 5011 5012 Currently only correct in parallel for square matrices. 5013 5014 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5015 @*/ 5016 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5017 { 5018 PetscFunctionBegin; 5019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5020 PetscValidType(mat, 1); 5021 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5022 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5023 MatCheckPreallocated(mat, 1); 5024 if (PetscDefined(USE_DEBUG)) { 5025 PetscInt nv, row, col, ndiag; 5026 5027 PetscCall(VecGetLocalSize(v, &nv)); 5028 PetscCall(MatGetLocalSize(mat, &row, &col)); 5029 ndiag = PetscMin(row, col); 5030 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); 5031 } 5032 5033 PetscUseTypeMethod(mat, getdiagonal, v); 5034 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5035 PetscFunctionReturn(PETSC_SUCCESS); 5036 } 5037 5038 /*@ 5039 MatGetRowMin - Gets the minimum value (of the real part) of each 5040 row of the matrix 5041 5042 Logically Collective 5043 5044 Input Parameter: 5045 . mat - the matrix 5046 5047 Output Parameters: 5048 + v - the vector for storing the maximums 5049 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5050 5051 Level: intermediate 5052 5053 Note: 5054 The result of this call are the same as if one converted the matrix to dense format 5055 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5056 5057 This code is only implemented for a couple of matrix formats. 5058 5059 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5060 `MatGetRowMax()` 5061 @*/ 5062 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5063 { 5064 PetscFunctionBegin; 5065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5066 PetscValidType(mat, 1); 5067 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5068 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5069 5070 if (!mat->cmap->N) { 5071 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5072 if (idx) { 5073 PetscInt i, m = mat->rmap->n; 5074 for (i = 0; i < m; i++) idx[i] = -1; 5075 } 5076 } else { 5077 MatCheckPreallocated(mat, 1); 5078 } 5079 PetscUseTypeMethod(mat, getrowmin, v, idx); 5080 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5081 PetscFunctionReturn(PETSC_SUCCESS); 5082 } 5083 5084 /*@ 5085 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5086 row of the matrix 5087 5088 Logically Collective 5089 5090 Input Parameter: 5091 . mat - the matrix 5092 5093 Output Parameters: 5094 + v - the vector for storing the minimums 5095 - idx - the indices of the column found for each row (or `NULL` if not needed) 5096 5097 Level: intermediate 5098 5099 Notes: 5100 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5101 row is 0 (the first column). 5102 5103 This code is only implemented for a couple of matrix formats. 5104 5105 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5106 @*/ 5107 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5108 { 5109 PetscFunctionBegin; 5110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5111 PetscValidType(mat, 1); 5112 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5113 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5114 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5115 5116 if (!mat->cmap->N) { 5117 PetscCall(VecSet(v, 0.0)); 5118 if (idx) { 5119 PetscInt i, m = mat->rmap->n; 5120 for (i = 0; i < m; i++) idx[i] = -1; 5121 } 5122 } else { 5123 MatCheckPreallocated(mat, 1); 5124 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5125 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5126 } 5127 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5128 PetscFunctionReturn(PETSC_SUCCESS); 5129 } 5130 5131 /*@ 5132 MatGetRowMax - Gets the maximum value (of the real part) of each 5133 row of the matrix 5134 5135 Logically Collective 5136 5137 Input Parameter: 5138 . mat - the matrix 5139 5140 Output Parameters: 5141 + v - the vector for storing the maximums 5142 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5143 5144 Level: intermediate 5145 5146 Notes: 5147 The result of this call are the same as if one converted the matrix to dense format 5148 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5149 5150 This code is only implemented for a couple of matrix formats. 5151 5152 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5153 @*/ 5154 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5155 { 5156 PetscFunctionBegin; 5157 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5158 PetscValidType(mat, 1); 5159 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5160 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5161 5162 if (!mat->cmap->N) { 5163 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5164 if (idx) { 5165 PetscInt i, m = mat->rmap->n; 5166 for (i = 0; i < m; i++) idx[i] = -1; 5167 } 5168 } else { 5169 MatCheckPreallocated(mat, 1); 5170 PetscUseTypeMethod(mat, getrowmax, v, idx); 5171 } 5172 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5173 PetscFunctionReturn(PETSC_SUCCESS); 5174 } 5175 5176 /*@ 5177 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5178 row of the matrix 5179 5180 Logically Collective 5181 5182 Input Parameter: 5183 . mat - the matrix 5184 5185 Output Parameters: 5186 + v - the vector for storing the maximums 5187 - idx - the indices of the column found for each row (or `NULL` if not needed) 5188 5189 Level: intermediate 5190 5191 Notes: 5192 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5193 row is 0 (the first column). 5194 5195 This code is only implemented for a couple of matrix formats. 5196 5197 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5198 @*/ 5199 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5200 { 5201 PetscFunctionBegin; 5202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5203 PetscValidType(mat, 1); 5204 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5205 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5206 5207 if (!mat->cmap->N) { 5208 PetscCall(VecSet(v, 0.0)); 5209 if (idx) { 5210 PetscInt i, m = mat->rmap->n; 5211 for (i = 0; i < m; i++) idx[i] = -1; 5212 } 5213 } else { 5214 MatCheckPreallocated(mat, 1); 5215 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5216 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5217 } 5218 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5219 PetscFunctionReturn(PETSC_SUCCESS); 5220 } 5221 5222 /*@ 5223 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5224 5225 Logically Collective 5226 5227 Input Parameter: 5228 . mat - the matrix 5229 5230 Output Parameter: 5231 . v - the vector for storing the sum 5232 5233 Level: intermediate 5234 5235 This code is only implemented for a couple of matrix formats. 5236 5237 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5238 @*/ 5239 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5240 { 5241 PetscFunctionBegin; 5242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5243 PetscValidType(mat, 1); 5244 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5245 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5246 5247 if (!mat->cmap->N) { 5248 PetscCall(VecSet(v, 0.0)); 5249 } else { 5250 MatCheckPreallocated(mat, 1); 5251 PetscUseTypeMethod(mat, getrowsumabs, v); 5252 } 5253 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5254 PetscFunctionReturn(PETSC_SUCCESS); 5255 } 5256 5257 /*@ 5258 MatGetRowSum - Gets the sum of each row of the matrix 5259 5260 Logically or Neighborhood Collective 5261 5262 Input Parameter: 5263 . mat - the matrix 5264 5265 Output Parameter: 5266 . v - the vector for storing the sum of rows 5267 5268 Level: intermediate 5269 5270 Note: 5271 This code is slow since it is not currently specialized for different formats 5272 5273 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5274 @*/ 5275 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5276 { 5277 Vec ones; 5278 5279 PetscFunctionBegin; 5280 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5281 PetscValidType(mat, 1); 5282 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5283 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5284 MatCheckPreallocated(mat, 1); 5285 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5286 PetscCall(VecSet(ones, 1.)); 5287 PetscCall(MatMult(mat, ones, v)); 5288 PetscCall(VecDestroy(&ones)); 5289 PetscFunctionReturn(PETSC_SUCCESS); 5290 } 5291 5292 /*@ 5293 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5294 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5295 5296 Collective 5297 5298 Input Parameter: 5299 . mat - the matrix to provide the transpose 5300 5301 Output Parameter: 5302 . 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 5303 5304 Level: advanced 5305 5306 Note: 5307 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 5308 routine allows bypassing that call. 5309 5310 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5311 @*/ 5312 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5313 { 5314 PetscContainer rB = NULL; 5315 MatParentState *rb = NULL; 5316 5317 PetscFunctionBegin; 5318 PetscCall(PetscNew(&rb)); 5319 rb->id = ((PetscObject)mat)->id; 5320 rb->state = 0; 5321 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5322 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5323 PetscCall(PetscContainerSetPointer(rB, rb)); 5324 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5325 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5326 PetscCall(PetscObjectDereference((PetscObject)rB)); 5327 PetscFunctionReturn(PETSC_SUCCESS); 5328 } 5329 5330 /*@ 5331 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5332 5333 Collective 5334 5335 Input Parameters: 5336 + mat - the matrix to transpose 5337 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5338 5339 Output Parameter: 5340 . B - the transpose 5341 5342 Level: intermediate 5343 5344 Notes: 5345 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5346 5347 `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 5348 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5349 5350 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. 5351 5352 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5353 5354 If mat is unchanged from the last call this function returns immediately without recomputing the result 5355 5356 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5357 5358 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5359 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5360 @*/ 5361 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5362 { 5363 PetscContainer rB = NULL; 5364 MatParentState *rb = NULL; 5365 5366 PetscFunctionBegin; 5367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5368 PetscValidType(mat, 1); 5369 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5370 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5371 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5372 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5373 MatCheckPreallocated(mat, 1); 5374 if (reuse == MAT_REUSE_MATRIX) { 5375 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5376 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5377 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5378 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5379 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5380 } 5381 5382 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5383 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5384 PetscUseTypeMethod(mat, transpose, reuse, B); 5385 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5386 } 5387 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5388 5389 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5390 if (reuse != MAT_INPLACE_MATRIX) { 5391 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5392 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5393 rb->state = ((PetscObject)mat)->state; 5394 rb->nonzerostate = mat->nonzerostate; 5395 } 5396 PetscFunctionReturn(PETSC_SUCCESS); 5397 } 5398 5399 /*@ 5400 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5401 5402 Collective 5403 5404 Input Parameter: 5405 . A - the matrix to transpose 5406 5407 Output Parameter: 5408 . 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 5409 numerical portion. 5410 5411 Level: intermediate 5412 5413 Note: 5414 This is not supported for many matrix types, use `MatTranspose()` in those cases 5415 5416 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5417 @*/ 5418 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5419 { 5420 PetscFunctionBegin; 5421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5422 PetscValidType(A, 1); 5423 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5424 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5425 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5426 PetscUseTypeMethod(A, transposesymbolic, B); 5427 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5428 5429 PetscCall(MatTransposeSetPrecursor(A, *B)); 5430 PetscFunctionReturn(PETSC_SUCCESS); 5431 } 5432 5433 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5434 { 5435 PetscContainer rB; 5436 MatParentState *rb; 5437 5438 PetscFunctionBegin; 5439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5440 PetscValidType(A, 1); 5441 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5442 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5443 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5444 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5445 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5446 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5447 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 /*@ 5452 MatIsTranspose - Test whether a matrix is another one's transpose, 5453 or its own, in which case it tests symmetry. 5454 5455 Collective 5456 5457 Input Parameters: 5458 + A - the matrix to test 5459 . B - the matrix to test against, this can equal the first parameter 5460 - tol - tolerance, differences between entries smaller than this are counted as zero 5461 5462 Output Parameter: 5463 . flg - the result 5464 5465 Level: intermediate 5466 5467 Notes: 5468 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5469 test involves parallel copies of the block off-diagonal parts of the matrix. 5470 5471 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5472 @*/ 5473 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5474 { 5475 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5476 5477 PetscFunctionBegin; 5478 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5479 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5480 PetscAssertPointer(flg, 4); 5481 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5482 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5483 *flg = PETSC_FALSE; 5484 if (f && g) { 5485 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5486 PetscCall((*f)(A, B, tol, flg)); 5487 } else { 5488 MatType mattype; 5489 5490 PetscCall(MatGetType(f ? B : A, &mattype)); 5491 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5492 } 5493 PetscFunctionReturn(PETSC_SUCCESS); 5494 } 5495 5496 /*@ 5497 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5498 5499 Collective 5500 5501 Input Parameters: 5502 + mat - the matrix to transpose and complex conjugate 5503 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5504 5505 Output Parameter: 5506 . B - the Hermitian transpose 5507 5508 Level: intermediate 5509 5510 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5511 @*/ 5512 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5513 { 5514 PetscFunctionBegin; 5515 PetscCall(MatTranspose(mat, reuse, B)); 5516 #if defined(PETSC_USE_COMPLEX) 5517 PetscCall(MatConjugate(*B)); 5518 #endif 5519 PetscFunctionReturn(PETSC_SUCCESS); 5520 } 5521 5522 /*@ 5523 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5524 5525 Collective 5526 5527 Input Parameters: 5528 + A - the matrix to test 5529 . B - the matrix to test against, this can equal the first parameter 5530 - tol - tolerance, differences between entries smaller than this are counted as zero 5531 5532 Output Parameter: 5533 . flg - the result 5534 5535 Level: intermediate 5536 5537 Notes: 5538 Only available for `MATAIJ` matrices. 5539 5540 The sequential algorithm 5541 has a running time of the order of the number of nonzeros; the parallel 5542 test involves parallel copies of the block off-diagonal parts of the matrix. 5543 5544 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5545 @*/ 5546 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5547 { 5548 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5549 5550 PetscFunctionBegin; 5551 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5552 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5553 PetscAssertPointer(flg, 4); 5554 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5555 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5556 if (f && g) { 5557 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5558 PetscCall((*f)(A, B, tol, flg)); 5559 } 5560 PetscFunctionReturn(PETSC_SUCCESS); 5561 } 5562 5563 /*@ 5564 MatPermute - Creates a new matrix with rows and columns permuted from the 5565 original. 5566 5567 Collective 5568 5569 Input Parameters: 5570 + mat - the matrix to permute 5571 . row - row permutation, each processor supplies only the permutation for its rows 5572 - col - column permutation, each processor supplies only the permutation for its columns 5573 5574 Output Parameter: 5575 . B - the permuted matrix 5576 5577 Level: advanced 5578 5579 Note: 5580 The index sets map from row/col of permuted matrix to row/col of original matrix. 5581 The index sets should be on the same communicator as mat and have the same local sizes. 5582 5583 Developer Note: 5584 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5585 exploit the fact that row and col are permutations, consider implementing the 5586 more general `MatCreateSubMatrix()` instead. 5587 5588 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5589 @*/ 5590 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5591 { 5592 PetscFunctionBegin; 5593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5594 PetscValidType(mat, 1); 5595 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5596 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5597 PetscAssertPointer(B, 4); 5598 PetscCheckSameComm(mat, 1, row, 2); 5599 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5601 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5602 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5603 MatCheckPreallocated(mat, 1); 5604 5605 if (mat->ops->permute) { 5606 PetscUseTypeMethod(mat, permute, row, col, B); 5607 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5608 } else { 5609 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5610 } 5611 PetscFunctionReturn(PETSC_SUCCESS); 5612 } 5613 5614 /*@ 5615 MatEqual - Compares two matrices. 5616 5617 Collective 5618 5619 Input Parameters: 5620 + A - the first matrix 5621 - B - the second matrix 5622 5623 Output Parameter: 5624 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5625 5626 Level: intermediate 5627 5628 .seealso: [](ch_matrices), `Mat` 5629 @*/ 5630 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5631 { 5632 PetscFunctionBegin; 5633 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5634 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5635 PetscValidType(A, 1); 5636 PetscValidType(B, 2); 5637 PetscAssertPointer(flg, 3); 5638 PetscCheckSameComm(A, 1, B, 2); 5639 MatCheckPreallocated(A, 1); 5640 MatCheckPreallocated(B, 2); 5641 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5642 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5643 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, 5644 B->cmap->N); 5645 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5646 PetscUseTypeMethod(A, equal, B, flg); 5647 } else { 5648 PetscCall(MatMultEqual(A, B, 10, flg)); 5649 } 5650 PetscFunctionReturn(PETSC_SUCCESS); 5651 } 5652 5653 /*@ 5654 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5655 matrices that are stored as vectors. Either of the two scaling 5656 matrices can be `NULL`. 5657 5658 Collective 5659 5660 Input Parameters: 5661 + mat - the matrix to be scaled 5662 . l - the left scaling vector (or `NULL`) 5663 - r - the right scaling vector (or `NULL`) 5664 5665 Level: intermediate 5666 5667 Note: 5668 `MatDiagonalScale()` computes $A = LAR$, where 5669 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5670 The L scales the rows of the matrix, the R scales the columns of the matrix. 5671 5672 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5673 @*/ 5674 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5675 { 5676 PetscFunctionBegin; 5677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5678 PetscValidType(mat, 1); 5679 if (l) { 5680 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5681 PetscCheckSameComm(mat, 1, l, 2); 5682 } 5683 if (r) { 5684 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5685 PetscCheckSameComm(mat, 1, r, 3); 5686 } 5687 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5688 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5689 MatCheckPreallocated(mat, 1); 5690 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5691 5692 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5693 PetscUseTypeMethod(mat, diagonalscale, l, r); 5694 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5695 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5696 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5697 PetscFunctionReturn(PETSC_SUCCESS); 5698 } 5699 5700 /*@ 5701 MatScale - Scales all elements of a matrix by a given number. 5702 5703 Logically Collective 5704 5705 Input Parameters: 5706 + mat - the matrix to be scaled 5707 - a - the scaling value 5708 5709 Level: intermediate 5710 5711 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5712 @*/ 5713 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5714 { 5715 PetscFunctionBegin; 5716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5717 PetscValidType(mat, 1); 5718 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5719 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5720 PetscValidLogicalCollectiveScalar(mat, a, 2); 5721 MatCheckPreallocated(mat, 1); 5722 5723 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5724 if (a != (PetscScalar)1.0) { 5725 PetscUseTypeMethod(mat, scale, a); 5726 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5727 } 5728 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5729 PetscFunctionReturn(PETSC_SUCCESS); 5730 } 5731 5732 /*@ 5733 MatNorm - Calculates various norms of a matrix. 5734 5735 Collective 5736 5737 Input Parameters: 5738 + mat - the matrix 5739 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5740 5741 Output Parameter: 5742 . nrm - the resulting norm 5743 5744 Level: intermediate 5745 5746 .seealso: [](ch_matrices), `Mat` 5747 @*/ 5748 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5749 { 5750 PetscFunctionBegin; 5751 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5752 PetscValidType(mat, 1); 5753 PetscAssertPointer(nrm, 3); 5754 5755 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5756 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5757 MatCheckPreallocated(mat, 1); 5758 5759 PetscUseTypeMethod(mat, norm, type, nrm); 5760 PetscFunctionReturn(PETSC_SUCCESS); 5761 } 5762 5763 /* 5764 This variable is used to prevent counting of MatAssemblyBegin() that 5765 are called from within a MatAssemblyEnd(). 5766 */ 5767 static PetscInt MatAssemblyEnd_InUse = 0; 5768 /*@ 5769 MatAssemblyBegin - Begins assembling the matrix. This routine should 5770 be called after completing all calls to `MatSetValues()`. 5771 5772 Collective 5773 5774 Input Parameters: 5775 + mat - the matrix 5776 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5777 5778 Level: beginner 5779 5780 Notes: 5781 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5782 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5783 5784 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5785 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5786 using the matrix. 5787 5788 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5789 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 5790 a global collective operation requiring all processes that share the matrix. 5791 5792 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5793 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5794 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5795 5796 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5797 @*/ 5798 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5799 { 5800 PetscFunctionBegin; 5801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5802 PetscValidType(mat, 1); 5803 MatCheckPreallocated(mat, 1); 5804 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5805 if (mat->assembled) { 5806 mat->was_assembled = PETSC_TRUE; 5807 mat->assembled = PETSC_FALSE; 5808 } 5809 5810 if (!MatAssemblyEnd_InUse) { 5811 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5812 PetscTryTypeMethod(mat, assemblybegin, type); 5813 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5814 } else PetscTryTypeMethod(mat, assemblybegin, type); 5815 PetscFunctionReturn(PETSC_SUCCESS); 5816 } 5817 5818 /*@ 5819 MatAssembled - Indicates if a matrix has been assembled and is ready for 5820 use; for example, in matrix-vector product. 5821 5822 Not Collective 5823 5824 Input Parameter: 5825 . mat - the matrix 5826 5827 Output Parameter: 5828 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5829 5830 Level: advanced 5831 5832 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5833 @*/ 5834 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5835 { 5836 PetscFunctionBegin; 5837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5838 PetscAssertPointer(assembled, 2); 5839 *assembled = mat->assembled; 5840 PetscFunctionReturn(PETSC_SUCCESS); 5841 } 5842 5843 /*@ 5844 MatAssemblyEnd - Completes assembling the matrix. This routine should 5845 be called after `MatAssemblyBegin()`. 5846 5847 Collective 5848 5849 Input Parameters: 5850 + mat - the matrix 5851 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5852 5853 Options Database Keys: 5854 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5855 . -mat_view ::ascii_info_detail - Prints more detailed info 5856 . -mat_view - Prints matrix in ASCII format 5857 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5858 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5859 . -display <name> - Sets display name (default is host) 5860 . -draw_pause <sec> - Sets number of seconds to pause after display 5861 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5862 . -viewer_socket_machine <machine> - Machine to use for socket 5863 . -viewer_socket_port <port> - Port number to use for socket 5864 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5865 5866 Level: beginner 5867 5868 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5869 @*/ 5870 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5871 { 5872 static PetscInt inassm = 0; 5873 PetscBool flg = PETSC_FALSE; 5874 5875 PetscFunctionBegin; 5876 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5877 PetscValidType(mat, 1); 5878 5879 inassm++; 5880 MatAssemblyEnd_InUse++; 5881 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5882 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5883 PetscTryTypeMethod(mat, assemblyend, type); 5884 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5885 } else PetscTryTypeMethod(mat, assemblyend, type); 5886 5887 /* Flush assembly is not a true assembly */ 5888 if (type != MAT_FLUSH_ASSEMBLY) { 5889 if (mat->num_ass) { 5890 if (!mat->symmetry_eternal) { 5891 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5892 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5893 } 5894 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5895 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5896 } 5897 mat->num_ass++; 5898 mat->assembled = PETSC_TRUE; 5899 mat->ass_nonzerostate = mat->nonzerostate; 5900 } 5901 5902 mat->insertmode = NOT_SET_VALUES; 5903 MatAssemblyEnd_InUse--; 5904 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5905 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5906 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5907 5908 if (mat->checksymmetryonassembly) { 5909 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5910 if (flg) { 5911 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5912 } else { 5913 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5914 } 5915 } 5916 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5917 } 5918 inassm--; 5919 PetscFunctionReturn(PETSC_SUCCESS); 5920 } 5921 5922 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5923 /*@ 5924 MatSetOption - Sets a parameter option for a matrix. Some options 5925 may be specific to certain storage formats. Some options 5926 determine how values will be inserted (or added). Sorted, 5927 row-oriented input will generally assemble the fastest. The default 5928 is row-oriented. 5929 5930 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5931 5932 Input Parameters: 5933 + mat - the matrix 5934 . op - the option, one of those listed below (and possibly others), 5935 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5936 5937 Options Describing Matrix Structure: 5938 + `MAT_SPD` - symmetric positive definite 5939 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5940 . `MAT_HERMITIAN` - transpose is the complex conjugation 5941 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5942 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5943 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5944 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5945 5946 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5947 do not need to be computed (usually at a high cost) 5948 5949 Options For Use with `MatSetValues()`: 5950 Insert a logically dense subblock, which can be 5951 . `MAT_ROW_ORIENTED` - row-oriented (default) 5952 5953 These options reflect the data you pass in with `MatSetValues()`; it has 5954 nothing to do with how the data is stored internally in the matrix 5955 data structure. 5956 5957 When (re)assembling a matrix, we can restrict the input for 5958 efficiency/debugging purposes. These options include 5959 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5960 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5961 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5962 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5963 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5964 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5965 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5966 performance for very large process counts. 5967 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5968 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5969 functions, instead sending only neighbor messages. 5970 5971 Level: intermediate 5972 5973 Notes: 5974 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5975 5976 Some options are relevant only for particular matrix types and 5977 are thus ignored by others. Other options are not supported by 5978 certain matrix types and will generate an error message if set. 5979 5980 If using Fortran to compute a matrix, one may need to 5981 use the column-oriented option (or convert to the row-oriented 5982 format). 5983 5984 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5985 that would generate a new entry in the nonzero structure is instead 5986 ignored. Thus, if memory has not already been allocated for this particular 5987 data, then the insertion is ignored. For dense matrices, in which 5988 the entire array is allocated, no entries are ever ignored. 5989 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5990 5991 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5992 that would generate a new entry in the nonzero structure instead produces 5993 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 5994 5995 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5996 that would generate a new entry that has not been preallocated will 5997 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5998 only.) This is a useful flag when debugging matrix memory preallocation. 5999 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6000 6001 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6002 other processors should be dropped, rather than stashed. 6003 This is useful if you know that the "owning" processor is also 6004 always generating the correct matrix entries, so that PETSc need 6005 not transfer duplicate entries generated on another processor. 6006 6007 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6008 searches during matrix assembly. When this flag is set, the hash table 6009 is created during the first matrix assembly. This hash table is 6010 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6011 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6012 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6013 supported by `MATMPIBAIJ` format only. 6014 6015 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6016 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6017 6018 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6019 a zero location in the matrix 6020 6021 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6022 6023 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6024 zero row routines and thus improves performance for very large process counts. 6025 6026 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6027 part of the matrix (since they should match the upper triangular part). 6028 6029 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6030 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6031 with finite difference schemes with non-periodic boundary conditions. 6032 6033 Developer Note: 6034 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6035 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6036 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6037 not changed. 6038 6039 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6040 @*/ 6041 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6042 { 6043 PetscFunctionBegin; 6044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6045 if (op > 0) { 6046 PetscValidLogicalCollectiveEnum(mat, op, 2); 6047 PetscValidLogicalCollectiveBool(mat, flg, 3); 6048 } 6049 6050 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); 6051 6052 switch (op) { 6053 case MAT_FORCE_DIAGONAL_ENTRIES: 6054 mat->force_diagonals = flg; 6055 PetscFunctionReturn(PETSC_SUCCESS); 6056 case MAT_NO_OFF_PROC_ENTRIES: 6057 mat->nooffprocentries = flg; 6058 PetscFunctionReturn(PETSC_SUCCESS); 6059 case MAT_SUBSET_OFF_PROC_ENTRIES: 6060 mat->assembly_subset = flg; 6061 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6062 #if !defined(PETSC_HAVE_MPIUNI) 6063 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6064 #endif 6065 mat->stash.first_assembly_done = PETSC_FALSE; 6066 } 6067 PetscFunctionReturn(PETSC_SUCCESS); 6068 case MAT_NO_OFF_PROC_ZERO_ROWS: 6069 mat->nooffproczerorows = flg; 6070 PetscFunctionReturn(PETSC_SUCCESS); 6071 case MAT_SPD: 6072 if (flg) { 6073 mat->spd = PETSC_BOOL3_TRUE; 6074 mat->symmetric = PETSC_BOOL3_TRUE; 6075 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6076 } else { 6077 mat->spd = PETSC_BOOL3_FALSE; 6078 } 6079 break; 6080 case MAT_SYMMETRIC: 6081 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6082 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6083 #if !defined(PETSC_USE_COMPLEX) 6084 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6085 #endif 6086 break; 6087 case MAT_HERMITIAN: 6088 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6089 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6090 #if !defined(PETSC_USE_COMPLEX) 6091 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6092 #endif 6093 break; 6094 case MAT_STRUCTURALLY_SYMMETRIC: 6095 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6096 break; 6097 case MAT_SYMMETRY_ETERNAL: 6098 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"); 6099 mat->symmetry_eternal = flg; 6100 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6101 break; 6102 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6103 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"); 6104 mat->structural_symmetry_eternal = flg; 6105 break; 6106 case MAT_SPD_ETERNAL: 6107 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"); 6108 mat->spd_eternal = flg; 6109 if (flg) { 6110 mat->structural_symmetry_eternal = PETSC_TRUE; 6111 mat->symmetry_eternal = PETSC_TRUE; 6112 } 6113 break; 6114 case MAT_STRUCTURE_ONLY: 6115 mat->structure_only = flg; 6116 break; 6117 case MAT_SORTED_FULL: 6118 mat->sortedfull = flg; 6119 break; 6120 default: 6121 break; 6122 } 6123 PetscTryTypeMethod(mat, setoption, op, flg); 6124 PetscFunctionReturn(PETSC_SUCCESS); 6125 } 6126 6127 /*@ 6128 MatGetOption - Gets a parameter option that has been set for a matrix. 6129 6130 Logically Collective 6131 6132 Input Parameters: 6133 + mat - the matrix 6134 - op - the option, this only responds to certain options, check the code for which ones 6135 6136 Output Parameter: 6137 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6138 6139 Level: intermediate 6140 6141 Notes: 6142 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6143 6144 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6145 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6146 6147 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6148 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6149 @*/ 6150 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6151 { 6152 PetscFunctionBegin; 6153 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6154 PetscValidType(mat, 1); 6155 6156 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); 6157 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()"); 6158 6159 switch (op) { 6160 case MAT_NO_OFF_PROC_ENTRIES: 6161 *flg = mat->nooffprocentries; 6162 break; 6163 case MAT_NO_OFF_PROC_ZERO_ROWS: 6164 *flg = mat->nooffproczerorows; 6165 break; 6166 case MAT_SYMMETRIC: 6167 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6168 break; 6169 case MAT_HERMITIAN: 6170 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6171 break; 6172 case MAT_STRUCTURALLY_SYMMETRIC: 6173 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6174 break; 6175 case MAT_SPD: 6176 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6177 break; 6178 case MAT_SYMMETRY_ETERNAL: 6179 *flg = mat->symmetry_eternal; 6180 break; 6181 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6182 *flg = mat->symmetry_eternal; 6183 break; 6184 default: 6185 break; 6186 } 6187 PetscFunctionReturn(PETSC_SUCCESS); 6188 } 6189 6190 /*@ 6191 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6192 this routine retains the old nonzero structure. 6193 6194 Logically Collective 6195 6196 Input Parameter: 6197 . mat - the matrix 6198 6199 Level: intermediate 6200 6201 Note: 6202 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. 6203 See the Performance chapter of the users manual for information on preallocating matrices. 6204 6205 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6206 @*/ 6207 PetscErrorCode MatZeroEntries(Mat mat) 6208 { 6209 PetscFunctionBegin; 6210 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6211 PetscValidType(mat, 1); 6212 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6213 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"); 6214 MatCheckPreallocated(mat, 1); 6215 6216 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6217 PetscUseTypeMethod(mat, zeroentries); 6218 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6219 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6220 PetscFunctionReturn(PETSC_SUCCESS); 6221 } 6222 6223 /*@ 6224 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6225 of a set of rows and columns of a matrix. 6226 6227 Collective 6228 6229 Input Parameters: 6230 + mat - the matrix 6231 . numRows - the number of rows/columns to zero 6232 . rows - the global row indices 6233 . diag - value put in the diagonal of the eliminated rows 6234 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6235 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6236 6237 Level: intermediate 6238 6239 Notes: 6240 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6241 6242 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6243 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 6244 6245 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6246 Krylov method to take advantage of the known solution on the zeroed rows. 6247 6248 For the parallel case, all processes that share the matrix (i.e., 6249 those in the communicator used for matrix creation) MUST call this 6250 routine, regardless of whether any rows being zeroed are owned by 6251 them. 6252 6253 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6254 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 6255 missing. 6256 6257 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6258 list only rows local to itself). 6259 6260 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6261 6262 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6263 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6264 @*/ 6265 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6266 { 6267 PetscFunctionBegin; 6268 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6269 PetscValidType(mat, 1); 6270 if (numRows) PetscAssertPointer(rows, 3); 6271 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6272 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6273 MatCheckPreallocated(mat, 1); 6274 6275 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6276 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6277 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6278 PetscFunctionReturn(PETSC_SUCCESS); 6279 } 6280 6281 /*@ 6282 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6283 of a set of rows and columns of a matrix. 6284 6285 Collective 6286 6287 Input Parameters: 6288 + mat - the matrix 6289 . is - the rows to zero 6290 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6291 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6292 - b - optional vector of right-hand side, that will be adjusted by provided solution 6293 6294 Level: intermediate 6295 6296 Note: 6297 See `MatZeroRowsColumns()` for details on how this routine operates. 6298 6299 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6300 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6301 @*/ 6302 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6303 { 6304 PetscInt numRows; 6305 const PetscInt *rows; 6306 6307 PetscFunctionBegin; 6308 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6309 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6310 PetscValidType(mat, 1); 6311 PetscValidType(is, 2); 6312 PetscCall(ISGetLocalSize(is, &numRows)); 6313 PetscCall(ISGetIndices(is, &rows)); 6314 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6315 PetscCall(ISRestoreIndices(is, &rows)); 6316 PetscFunctionReturn(PETSC_SUCCESS); 6317 } 6318 6319 /*@ 6320 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6321 of a set of rows of a matrix. 6322 6323 Collective 6324 6325 Input Parameters: 6326 + mat - the matrix 6327 . numRows - the number of rows to zero 6328 . rows - the global row indices 6329 . diag - value put in the diagonal of the zeroed rows 6330 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6331 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6332 6333 Level: intermediate 6334 6335 Notes: 6336 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6337 6338 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6339 6340 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6341 Krylov method to take advantage of the known solution on the zeroed rows. 6342 6343 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) 6344 from the matrix. 6345 6346 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6347 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 6348 formats this does not alter the nonzero structure. 6349 6350 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6351 of the matrix is not changed the values are 6352 merely zeroed. 6353 6354 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6355 formats can optionally remove the main diagonal entry from the 6356 nonzero structure as well, by passing 0.0 as the final argument). 6357 6358 For the parallel case, all processes that share the matrix (i.e., 6359 those in the communicator used for matrix creation) MUST call this 6360 routine, regardless of whether any rows being zeroed are owned by 6361 them. 6362 6363 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6364 list only rows local to itself). 6365 6366 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6367 owns that are to be zeroed. This saves a global synchronization in the implementation. 6368 6369 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6370 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6371 @*/ 6372 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6373 { 6374 PetscFunctionBegin; 6375 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6376 PetscValidType(mat, 1); 6377 if (numRows) PetscAssertPointer(rows, 3); 6378 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6379 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6380 MatCheckPreallocated(mat, 1); 6381 6382 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6383 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6384 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6385 PetscFunctionReturn(PETSC_SUCCESS); 6386 } 6387 6388 /*@ 6389 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6390 of a set of rows of a matrix. 6391 6392 Collective 6393 6394 Input Parameters: 6395 + mat - the matrix 6396 . is - index set of rows to remove (if `NULL` then no row is removed) 6397 . diag - value put in all diagonals of eliminated rows 6398 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6399 - b - optional vector of right-hand side, that will be adjusted by provided solution 6400 6401 Level: intermediate 6402 6403 Note: 6404 See `MatZeroRows()` for details on how this routine operates. 6405 6406 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6407 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6408 @*/ 6409 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6410 { 6411 PetscInt numRows = 0; 6412 const PetscInt *rows = NULL; 6413 6414 PetscFunctionBegin; 6415 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6416 PetscValidType(mat, 1); 6417 if (is) { 6418 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6419 PetscCall(ISGetLocalSize(is, &numRows)); 6420 PetscCall(ISGetIndices(is, &rows)); 6421 } 6422 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6423 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6424 PetscFunctionReturn(PETSC_SUCCESS); 6425 } 6426 6427 /*@ 6428 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6429 of a set of rows of a matrix. These rows must be local to the process. 6430 6431 Collective 6432 6433 Input Parameters: 6434 + mat - the matrix 6435 . numRows - the number of rows to remove 6436 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6437 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6438 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6439 - b - optional vector of right-hand side, that will be adjusted by provided solution 6440 6441 Level: intermediate 6442 6443 Notes: 6444 See `MatZeroRows()` for details on how this routine operates. 6445 6446 The grid coordinates are across the entire grid, not just the local portion 6447 6448 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6449 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6450 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6451 `DM_BOUNDARY_PERIODIC` boundary type. 6452 6453 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 6454 a single value per point) you can skip filling those indices. 6455 6456 Fortran Note: 6457 `idxm` and `idxn` should be declared as 6458 $ MatStencil idxm(4, m) 6459 and the values inserted using 6460 .vb 6461 idxm(MatStencil_i, 1) = i 6462 idxm(MatStencil_j, 1) = j 6463 idxm(MatStencil_k, 1) = k 6464 idxm(MatStencil_c, 1) = c 6465 etc 6466 .ve 6467 6468 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6469 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6470 @*/ 6471 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6472 { 6473 PetscInt dim = mat->stencil.dim; 6474 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6475 PetscInt *dims = mat->stencil.dims + 1; 6476 PetscInt *starts = mat->stencil.starts; 6477 PetscInt *dxm = (PetscInt *)rows; 6478 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6479 6480 PetscFunctionBegin; 6481 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6482 PetscValidType(mat, 1); 6483 if (numRows) PetscAssertPointer(rows, 3); 6484 6485 PetscCall(PetscMalloc1(numRows, &jdxm)); 6486 for (i = 0; i < numRows; ++i) { 6487 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6488 for (j = 0; j < 3 - sdim; ++j) dxm++; 6489 /* Local index in X dir */ 6490 tmp = *dxm++ - starts[0]; 6491 /* Loop over remaining dimensions */ 6492 for (j = 0; j < dim - 1; ++j) { 6493 /* If nonlocal, set index to be negative */ 6494 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6495 /* Update local index */ 6496 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6497 } 6498 /* Skip component slot if necessary */ 6499 if (mat->stencil.noc) dxm++; 6500 /* Local row number */ 6501 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6502 } 6503 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6504 PetscCall(PetscFree(jdxm)); 6505 PetscFunctionReturn(PETSC_SUCCESS); 6506 } 6507 6508 /*@ 6509 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6510 of a set of rows and columns of a matrix. 6511 6512 Collective 6513 6514 Input Parameters: 6515 + mat - the matrix 6516 . numRows - the number of rows/columns to remove 6517 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6518 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6519 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6520 - b - optional vector of right-hand side, that will be adjusted by provided solution 6521 6522 Level: intermediate 6523 6524 Notes: 6525 See `MatZeroRowsColumns()` for details on how this routine operates. 6526 6527 The grid coordinates are across the entire grid, not just the local portion 6528 6529 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6530 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6531 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6532 `DM_BOUNDARY_PERIODIC` boundary type. 6533 6534 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 6535 a single value per point) you can skip filling those indices. 6536 6537 Fortran Note: 6538 `idxm` and `idxn` should be declared as 6539 $ MatStencil idxm(4, m) 6540 and the values inserted using 6541 .vb 6542 idxm(MatStencil_i, 1) = i 6543 idxm(MatStencil_j, 1) = j 6544 idxm(MatStencil_k, 1) = k 6545 idxm(MatStencil_c, 1) = c 6546 etc 6547 .ve 6548 6549 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6550 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6551 @*/ 6552 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6553 { 6554 PetscInt dim = mat->stencil.dim; 6555 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6556 PetscInt *dims = mat->stencil.dims + 1; 6557 PetscInt *starts = mat->stencil.starts; 6558 PetscInt *dxm = (PetscInt *)rows; 6559 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6560 6561 PetscFunctionBegin; 6562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6563 PetscValidType(mat, 1); 6564 if (numRows) PetscAssertPointer(rows, 3); 6565 6566 PetscCall(PetscMalloc1(numRows, &jdxm)); 6567 for (i = 0; i < numRows; ++i) { 6568 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6569 for (j = 0; j < 3 - sdim; ++j) dxm++; 6570 /* Local index in X dir */ 6571 tmp = *dxm++ - starts[0]; 6572 /* Loop over remaining dimensions */ 6573 for (j = 0; j < dim - 1; ++j) { 6574 /* If nonlocal, set index to be negative */ 6575 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6576 /* Update local index */ 6577 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6578 } 6579 /* Skip component slot if necessary */ 6580 if (mat->stencil.noc) dxm++; 6581 /* Local row number */ 6582 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6583 } 6584 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6585 PetscCall(PetscFree(jdxm)); 6586 PetscFunctionReturn(PETSC_SUCCESS); 6587 } 6588 6589 /*@ 6590 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6591 of a set of rows of a matrix; using local numbering of rows. 6592 6593 Collective 6594 6595 Input Parameters: 6596 + mat - the matrix 6597 . numRows - the number of rows to remove 6598 . rows - the local row indices 6599 . diag - value put in all diagonals of eliminated rows 6600 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6601 - b - optional vector of right-hand side, that will be adjusted by provided solution 6602 6603 Level: intermediate 6604 6605 Notes: 6606 Before calling `MatZeroRowsLocal()`, the user must first set the 6607 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6608 6609 See `MatZeroRows()` for details on how this routine operates. 6610 6611 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6612 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6613 @*/ 6614 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6615 { 6616 PetscFunctionBegin; 6617 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6618 PetscValidType(mat, 1); 6619 if (numRows) PetscAssertPointer(rows, 3); 6620 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6621 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6622 MatCheckPreallocated(mat, 1); 6623 6624 if (mat->ops->zerorowslocal) { 6625 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6626 } else { 6627 IS is, newis; 6628 const PetscInt *newRows; 6629 6630 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6631 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6632 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6633 PetscCall(ISGetIndices(newis, &newRows)); 6634 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6635 PetscCall(ISRestoreIndices(newis, &newRows)); 6636 PetscCall(ISDestroy(&newis)); 6637 PetscCall(ISDestroy(&is)); 6638 } 6639 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6640 PetscFunctionReturn(PETSC_SUCCESS); 6641 } 6642 6643 /*@ 6644 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6645 of a set of rows of a matrix; using local numbering of rows. 6646 6647 Collective 6648 6649 Input Parameters: 6650 + mat - the matrix 6651 . is - index set of rows to remove 6652 . diag - value put in all diagonals of eliminated rows 6653 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6654 - b - optional vector of right-hand side, that will be adjusted by provided solution 6655 6656 Level: intermediate 6657 6658 Notes: 6659 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6660 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6661 6662 See `MatZeroRows()` for details on how this routine operates. 6663 6664 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6665 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6666 @*/ 6667 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6668 { 6669 PetscInt numRows; 6670 const PetscInt *rows; 6671 6672 PetscFunctionBegin; 6673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6674 PetscValidType(mat, 1); 6675 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6676 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6677 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6678 MatCheckPreallocated(mat, 1); 6679 6680 PetscCall(ISGetLocalSize(is, &numRows)); 6681 PetscCall(ISGetIndices(is, &rows)); 6682 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6683 PetscCall(ISRestoreIndices(is, &rows)); 6684 PetscFunctionReturn(PETSC_SUCCESS); 6685 } 6686 6687 /*@ 6688 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6689 of a set of rows and columns of a matrix; using local numbering of rows. 6690 6691 Collective 6692 6693 Input Parameters: 6694 + mat - the matrix 6695 . numRows - the number of rows to remove 6696 . rows - the global row indices 6697 . diag - value put in all diagonals of eliminated rows 6698 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6699 - b - optional vector of right-hand side, that will be adjusted by provided solution 6700 6701 Level: intermediate 6702 6703 Notes: 6704 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6705 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6706 6707 See `MatZeroRowsColumns()` for details on how this routine operates. 6708 6709 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6710 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6711 @*/ 6712 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6713 { 6714 IS is, newis; 6715 const PetscInt *newRows; 6716 6717 PetscFunctionBegin; 6718 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6719 PetscValidType(mat, 1); 6720 if (numRows) PetscAssertPointer(rows, 3); 6721 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6722 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6723 MatCheckPreallocated(mat, 1); 6724 6725 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6726 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6727 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6728 PetscCall(ISGetIndices(newis, &newRows)); 6729 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6730 PetscCall(ISRestoreIndices(newis, &newRows)); 6731 PetscCall(ISDestroy(&newis)); 6732 PetscCall(ISDestroy(&is)); 6733 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6734 PetscFunctionReturn(PETSC_SUCCESS); 6735 } 6736 6737 /*@ 6738 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6739 of a set of rows and columns of a matrix; using local numbering of rows. 6740 6741 Collective 6742 6743 Input Parameters: 6744 + mat - the matrix 6745 . is - index set of rows to remove 6746 . diag - value put in all diagonals of eliminated rows 6747 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6748 - b - optional vector of right-hand side, that will be adjusted by provided solution 6749 6750 Level: intermediate 6751 6752 Notes: 6753 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6754 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6755 6756 See `MatZeroRowsColumns()` for details on how this routine operates. 6757 6758 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6759 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6760 @*/ 6761 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6762 { 6763 PetscInt numRows; 6764 const PetscInt *rows; 6765 6766 PetscFunctionBegin; 6767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6768 PetscValidType(mat, 1); 6769 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6770 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6771 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6772 MatCheckPreallocated(mat, 1); 6773 6774 PetscCall(ISGetLocalSize(is, &numRows)); 6775 PetscCall(ISGetIndices(is, &rows)); 6776 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6777 PetscCall(ISRestoreIndices(is, &rows)); 6778 PetscFunctionReturn(PETSC_SUCCESS); 6779 } 6780 6781 /*@ 6782 MatGetSize - Returns the numbers of rows and columns in a matrix. 6783 6784 Not Collective 6785 6786 Input Parameter: 6787 . mat - the matrix 6788 6789 Output Parameters: 6790 + m - the number of global rows 6791 - n - the number of global columns 6792 6793 Level: beginner 6794 6795 Note: 6796 Both output parameters can be `NULL` on input. 6797 6798 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6799 @*/ 6800 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6801 { 6802 PetscFunctionBegin; 6803 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6804 if (m) *m = mat->rmap->N; 6805 if (n) *n = mat->cmap->N; 6806 PetscFunctionReturn(PETSC_SUCCESS); 6807 } 6808 6809 /*@ 6810 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6811 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6812 6813 Not Collective 6814 6815 Input Parameter: 6816 . mat - the matrix 6817 6818 Output Parameters: 6819 + m - the number of local rows, use `NULL` to not obtain this value 6820 - n - the number of local columns, use `NULL` to not obtain this value 6821 6822 Level: beginner 6823 6824 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6825 @*/ 6826 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6827 { 6828 PetscFunctionBegin; 6829 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6830 if (m) PetscAssertPointer(m, 2); 6831 if (n) PetscAssertPointer(n, 3); 6832 if (m) *m = mat->rmap->n; 6833 if (n) *n = mat->cmap->n; 6834 PetscFunctionReturn(PETSC_SUCCESS); 6835 } 6836 6837 /*@ 6838 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6839 vector one multiplies this matrix by that are owned by this processor. 6840 6841 Not Collective, unless matrix has not been allocated, then collective 6842 6843 Input Parameter: 6844 . mat - the matrix 6845 6846 Output Parameters: 6847 + m - the global index of the first local column, use `NULL` to not obtain this value 6848 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6849 6850 Level: developer 6851 6852 Notes: 6853 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6854 6855 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6856 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6857 6858 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6859 the local values in the matrix. 6860 6861 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6862 Layouts](sec_matlayout) for details on matrix layouts. 6863 6864 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6865 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6866 @*/ 6867 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6868 { 6869 PetscFunctionBegin; 6870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6871 PetscValidType(mat, 1); 6872 if (m) PetscAssertPointer(m, 2); 6873 if (n) PetscAssertPointer(n, 3); 6874 MatCheckPreallocated(mat, 1); 6875 if (m) *m = mat->cmap->rstart; 6876 if (n) *n = mat->cmap->rend; 6877 PetscFunctionReturn(PETSC_SUCCESS); 6878 } 6879 6880 /*@ 6881 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6882 this MPI process. 6883 6884 Not Collective 6885 6886 Input Parameter: 6887 . mat - the matrix 6888 6889 Output Parameters: 6890 + m - the global index of the first local row, use `NULL` to not obtain this value 6891 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6892 6893 Level: beginner 6894 6895 Notes: 6896 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6897 6898 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6899 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6900 6901 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6902 the local values in the matrix. 6903 6904 The high argument is one more than the last element stored locally. 6905 6906 For all matrices it returns the range of matrix rows associated with rows of a vector that 6907 would contain the result of a matrix vector product with this matrix. See [Matrix 6908 Layouts](sec_matlayout) for details on matrix layouts. 6909 6910 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6911 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6912 @*/ 6913 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6914 { 6915 PetscFunctionBegin; 6916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6917 PetscValidType(mat, 1); 6918 if (m) PetscAssertPointer(m, 2); 6919 if (n) PetscAssertPointer(n, 3); 6920 MatCheckPreallocated(mat, 1); 6921 if (m) *m = mat->rmap->rstart; 6922 if (n) *n = mat->rmap->rend; 6923 PetscFunctionReturn(PETSC_SUCCESS); 6924 } 6925 6926 /*@C 6927 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6928 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6929 6930 Not Collective, unless matrix has not been allocated 6931 6932 Input Parameter: 6933 . mat - the matrix 6934 6935 Output Parameter: 6936 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6937 where `size` is the number of MPI processes used by `mat` 6938 6939 Level: beginner 6940 6941 Notes: 6942 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6943 6944 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6945 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6946 6947 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6948 the local values in the matrix. 6949 6950 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6951 would contain the result of a matrix vector product with this matrix. See [Matrix 6952 Layouts](sec_matlayout) for details on matrix layouts. 6953 6954 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6955 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6956 `DMDAGetGhostCorners()`, `DM` 6957 @*/ 6958 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6959 { 6960 PetscFunctionBegin; 6961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6962 PetscValidType(mat, 1); 6963 MatCheckPreallocated(mat, 1); 6964 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6965 PetscFunctionReturn(PETSC_SUCCESS); 6966 } 6967 6968 /*@C 6969 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6970 vector one multiplies this vector by that are owned by each processor. 6971 6972 Not Collective, unless matrix has not been allocated 6973 6974 Input Parameter: 6975 . mat - the matrix 6976 6977 Output Parameter: 6978 . ranges - start of each processors portion plus one more than the total length at the end 6979 6980 Level: beginner 6981 6982 Notes: 6983 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6984 6985 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6986 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6987 6988 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6989 the local values in the matrix. 6990 6991 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6992 Layouts](sec_matlayout) for details on matrix layouts. 6993 6994 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6995 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6996 `DMDAGetGhostCorners()`, `DM` 6997 @*/ 6998 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6999 { 7000 PetscFunctionBegin; 7001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7002 PetscValidType(mat, 1); 7003 MatCheckPreallocated(mat, 1); 7004 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7005 PetscFunctionReturn(PETSC_SUCCESS); 7006 } 7007 7008 /*@ 7009 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7010 7011 Not Collective 7012 7013 Input Parameter: 7014 . A - matrix 7015 7016 Output Parameters: 7017 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7018 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7019 7020 Level: intermediate 7021 7022 Note: 7023 You should call `ISDestroy()` on the returned `IS` 7024 7025 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7026 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7027 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7028 details on matrix layouts. 7029 7030 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7031 @*/ 7032 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7033 { 7034 PetscErrorCode (*f)(Mat, IS *, IS *); 7035 7036 PetscFunctionBegin; 7037 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7038 PetscValidType(A, 1); 7039 MatCheckPreallocated(A, 1); 7040 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7041 if (f) { 7042 PetscCall((*f)(A, rows, cols)); 7043 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7044 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7045 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7046 } 7047 PetscFunctionReturn(PETSC_SUCCESS); 7048 } 7049 7050 /*@ 7051 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7052 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7053 to complete the factorization. 7054 7055 Collective 7056 7057 Input Parameters: 7058 + fact - the factorized matrix obtained with `MatGetFactor()` 7059 . mat - the matrix 7060 . row - row permutation 7061 . col - column permutation 7062 - info - structure containing 7063 .vb 7064 levels - number of levels of fill. 7065 expected fill - as ratio of original fill. 7066 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7067 missing diagonal entries) 7068 .ve 7069 7070 Level: developer 7071 7072 Notes: 7073 See [Matrix Factorization](sec_matfactor) for additional information. 7074 7075 Most users should employ the `KSP` interface for linear solvers 7076 instead of working directly with matrix algebra routines such as this. 7077 See, e.g., `KSPCreate()`. 7078 7079 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7080 7081 Developer Note: 7082 The Fortran interface is not autogenerated as the 7083 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7084 7085 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7086 `MatGetOrdering()`, `MatFactorInfo` 7087 @*/ 7088 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7089 { 7090 PetscFunctionBegin; 7091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7092 PetscValidType(mat, 2); 7093 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7094 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7095 PetscAssertPointer(info, 5); 7096 PetscAssertPointer(fact, 1); 7097 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7098 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7099 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7100 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7101 MatCheckPreallocated(mat, 2); 7102 7103 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7104 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7105 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7106 PetscFunctionReturn(PETSC_SUCCESS); 7107 } 7108 7109 /*@ 7110 MatICCFactorSymbolic - Performs symbolic incomplete 7111 Cholesky factorization for a symmetric matrix. Use 7112 `MatCholeskyFactorNumeric()` to complete the factorization. 7113 7114 Collective 7115 7116 Input Parameters: 7117 + fact - the factorized matrix obtained with `MatGetFactor()` 7118 . mat - the matrix to be factored 7119 . perm - row and column permutation 7120 - info - structure containing 7121 .vb 7122 levels - number of levels of fill. 7123 expected fill - as ratio of original fill. 7124 .ve 7125 7126 Level: developer 7127 7128 Notes: 7129 Most users should employ the `KSP` interface for linear solvers 7130 instead of working directly with matrix algebra routines such as this. 7131 See, e.g., `KSPCreate()`. 7132 7133 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7134 7135 Developer Note: 7136 The Fortran interface is not autogenerated as the 7137 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7138 7139 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7140 @*/ 7141 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7142 { 7143 PetscFunctionBegin; 7144 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7145 PetscValidType(mat, 2); 7146 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7147 PetscAssertPointer(info, 4); 7148 PetscAssertPointer(fact, 1); 7149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7150 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7151 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7153 MatCheckPreallocated(mat, 2); 7154 7155 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7156 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7157 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7158 PetscFunctionReturn(PETSC_SUCCESS); 7159 } 7160 7161 /*@C 7162 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7163 points to an array of valid matrices, they may be reused to store the new 7164 submatrices. 7165 7166 Collective 7167 7168 Input Parameters: 7169 + mat - the matrix 7170 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7171 . irow - index set of rows to extract 7172 . icol - index set of columns to extract 7173 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7174 7175 Output Parameter: 7176 . submat - the array of submatrices 7177 7178 Level: advanced 7179 7180 Notes: 7181 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7182 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7183 to extract a parallel submatrix. 7184 7185 Some matrix types place restrictions on the row and column 7186 indices, such as that they be sorted or that they be equal to each other. 7187 7188 The index sets may not have duplicate entries. 7189 7190 When extracting submatrices from a parallel matrix, each processor can 7191 form a different submatrix by setting the rows and columns of its 7192 individual index sets according to the local submatrix desired. 7193 7194 When finished using the submatrices, the user should destroy 7195 them with `MatDestroySubMatrices()`. 7196 7197 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7198 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7199 7200 This routine creates the matrices in submat; you should NOT create them before 7201 calling it. It also allocates the array of matrix pointers submat. 7202 7203 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7204 request one row/column in a block, they must request all rows/columns that are in 7205 that block. For example, if the block size is 2 you cannot request just row 0 and 7206 column 0. 7207 7208 Fortran Note: 7209 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7210 7211 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7212 @*/ 7213 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7214 { 7215 PetscInt i; 7216 PetscBool eq; 7217 7218 PetscFunctionBegin; 7219 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7220 PetscValidType(mat, 1); 7221 if (n) { 7222 PetscAssertPointer(irow, 3); 7223 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7224 PetscAssertPointer(icol, 4); 7225 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7226 } 7227 PetscAssertPointer(submat, 6); 7228 if (n && scall == MAT_REUSE_MATRIX) { 7229 PetscAssertPointer(*submat, 6); 7230 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7231 } 7232 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7233 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7234 MatCheckPreallocated(mat, 1); 7235 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7236 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7237 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7238 for (i = 0; i < n; i++) { 7239 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7240 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7241 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7242 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7243 if (mat->boundtocpu && mat->bindingpropagates) { 7244 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7245 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7246 } 7247 #endif 7248 } 7249 PetscFunctionReturn(PETSC_SUCCESS); 7250 } 7251 7252 /*@C 7253 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7254 7255 Collective 7256 7257 Input Parameters: 7258 + mat - the matrix 7259 . n - the number of submatrixes to be extracted 7260 . irow - index set of rows to extract 7261 . icol - index set of columns to extract 7262 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7263 7264 Output Parameter: 7265 . submat - the array of submatrices 7266 7267 Level: advanced 7268 7269 Note: 7270 This is used by `PCGASM` 7271 7272 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7273 @*/ 7274 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7275 { 7276 PetscInt i; 7277 PetscBool eq; 7278 7279 PetscFunctionBegin; 7280 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7281 PetscValidType(mat, 1); 7282 if (n) { 7283 PetscAssertPointer(irow, 3); 7284 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7285 PetscAssertPointer(icol, 4); 7286 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7287 } 7288 PetscAssertPointer(submat, 6); 7289 if (n && scall == MAT_REUSE_MATRIX) { 7290 PetscAssertPointer(*submat, 6); 7291 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7292 } 7293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7294 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7295 MatCheckPreallocated(mat, 1); 7296 7297 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7298 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7299 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7300 for (i = 0; i < n; i++) { 7301 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7302 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7303 } 7304 PetscFunctionReturn(PETSC_SUCCESS); 7305 } 7306 7307 /*@C 7308 MatDestroyMatrices - Destroys an array of matrices. 7309 7310 Collective 7311 7312 Input Parameters: 7313 + n - the number of local matrices 7314 - mat - the matrices (this is a pointer to the array of matrices) 7315 7316 Level: advanced 7317 7318 Notes: 7319 Frees not only the matrices, but also the array that contains the matrices 7320 7321 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7322 7323 Fortran Note: 7324 Does not free the `mat` array. 7325 7326 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7327 @*/ 7328 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7329 { 7330 PetscInt i; 7331 7332 PetscFunctionBegin; 7333 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7334 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7335 PetscAssertPointer(mat, 2); 7336 7337 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7338 7339 /* memory is allocated even if n = 0 */ 7340 PetscCall(PetscFree(*mat)); 7341 PetscFunctionReturn(PETSC_SUCCESS); 7342 } 7343 7344 /*@C 7345 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7346 7347 Collective 7348 7349 Input Parameters: 7350 + n - the number of local matrices 7351 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7352 sequence of `MatCreateSubMatrices()`) 7353 7354 Level: advanced 7355 7356 Note: 7357 Frees not only the matrices, but also the array that contains the matrices 7358 7359 Fortran Note: 7360 Does not free the `mat` array. 7361 7362 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7363 @*/ 7364 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7365 { 7366 Mat mat0; 7367 7368 PetscFunctionBegin; 7369 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7370 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7371 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7372 PetscAssertPointer(mat, 2); 7373 7374 mat0 = (*mat)[0]; 7375 if (mat0 && mat0->ops->destroysubmatrices) { 7376 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7377 } else { 7378 PetscCall(MatDestroyMatrices(n, mat)); 7379 } 7380 PetscFunctionReturn(PETSC_SUCCESS); 7381 } 7382 7383 /*@ 7384 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7385 7386 Collective 7387 7388 Input Parameter: 7389 . mat - the matrix 7390 7391 Output Parameter: 7392 . matstruct - the sequential matrix with the nonzero structure of `mat` 7393 7394 Level: developer 7395 7396 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7397 @*/ 7398 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7399 { 7400 PetscFunctionBegin; 7401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7402 PetscAssertPointer(matstruct, 2); 7403 7404 PetscValidType(mat, 1); 7405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7406 MatCheckPreallocated(mat, 1); 7407 7408 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7409 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7410 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7411 PetscFunctionReturn(PETSC_SUCCESS); 7412 } 7413 7414 /*@C 7415 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7416 7417 Collective 7418 7419 Input Parameter: 7420 . mat - the matrix 7421 7422 Level: advanced 7423 7424 Note: 7425 This is not needed, one can just call `MatDestroy()` 7426 7427 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7428 @*/ 7429 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7430 { 7431 PetscFunctionBegin; 7432 PetscAssertPointer(mat, 1); 7433 PetscCall(MatDestroy(mat)); 7434 PetscFunctionReturn(PETSC_SUCCESS); 7435 } 7436 7437 /*@ 7438 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7439 replaces the index sets by larger ones that represent submatrices with 7440 additional overlap. 7441 7442 Collective 7443 7444 Input Parameters: 7445 + mat - the matrix 7446 . n - the number of index sets 7447 . is - the array of index sets (these index sets will changed during the call) 7448 - ov - the additional overlap requested 7449 7450 Options Database Key: 7451 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7452 7453 Level: developer 7454 7455 Note: 7456 The computed overlap preserves the matrix block sizes when the blocks are square. 7457 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7458 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7459 7460 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7461 @*/ 7462 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7463 { 7464 PetscInt i, bs, cbs; 7465 7466 PetscFunctionBegin; 7467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7468 PetscValidType(mat, 1); 7469 PetscValidLogicalCollectiveInt(mat, n, 2); 7470 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7471 if (n) { 7472 PetscAssertPointer(is, 3); 7473 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7474 } 7475 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7476 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7477 MatCheckPreallocated(mat, 1); 7478 7479 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7480 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7481 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7482 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7483 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7484 if (bs == cbs) { 7485 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7486 } 7487 PetscFunctionReturn(PETSC_SUCCESS); 7488 } 7489 7490 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7491 7492 /*@ 7493 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7494 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7495 additional overlap. 7496 7497 Collective 7498 7499 Input Parameters: 7500 + mat - the matrix 7501 . n - the number of index sets 7502 . is - the array of index sets (these index sets will changed during the call) 7503 - ov - the additional overlap requested 7504 7505 ` Options Database Key: 7506 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7507 7508 Level: developer 7509 7510 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7511 @*/ 7512 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7513 { 7514 PetscInt i; 7515 7516 PetscFunctionBegin; 7517 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7518 PetscValidType(mat, 1); 7519 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7520 if (n) { 7521 PetscAssertPointer(is, 3); 7522 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7523 } 7524 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7525 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7526 MatCheckPreallocated(mat, 1); 7527 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7528 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7529 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7530 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7531 PetscFunctionReturn(PETSC_SUCCESS); 7532 } 7533 7534 /*@ 7535 MatGetBlockSize - Returns the matrix block size. 7536 7537 Not Collective 7538 7539 Input Parameter: 7540 . mat - the matrix 7541 7542 Output Parameter: 7543 . bs - block size 7544 7545 Level: intermediate 7546 7547 Notes: 7548 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7549 7550 If the block size has not been set yet this routine returns 1. 7551 7552 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7553 @*/ 7554 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7555 { 7556 PetscFunctionBegin; 7557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7558 PetscAssertPointer(bs, 2); 7559 *bs = PetscAbs(mat->rmap->bs); 7560 PetscFunctionReturn(PETSC_SUCCESS); 7561 } 7562 7563 /*@ 7564 MatGetBlockSizes - Returns the matrix block row and column sizes. 7565 7566 Not Collective 7567 7568 Input Parameter: 7569 . mat - the matrix 7570 7571 Output Parameters: 7572 + rbs - row block size 7573 - cbs - column block size 7574 7575 Level: intermediate 7576 7577 Notes: 7578 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7579 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7580 7581 If a block size has not been set yet this routine returns 1. 7582 7583 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7584 @*/ 7585 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7586 { 7587 PetscFunctionBegin; 7588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7589 if (rbs) PetscAssertPointer(rbs, 2); 7590 if (cbs) PetscAssertPointer(cbs, 3); 7591 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7592 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7593 PetscFunctionReturn(PETSC_SUCCESS); 7594 } 7595 7596 /*@ 7597 MatSetBlockSize - Sets the matrix block size. 7598 7599 Logically Collective 7600 7601 Input Parameters: 7602 + mat - the matrix 7603 - bs - block size 7604 7605 Level: intermediate 7606 7607 Notes: 7608 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7609 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7610 7611 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7612 is compatible with the matrix local sizes. 7613 7614 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7615 @*/ 7616 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7617 { 7618 PetscFunctionBegin; 7619 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7620 PetscValidLogicalCollectiveInt(mat, bs, 2); 7621 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7622 PetscFunctionReturn(PETSC_SUCCESS); 7623 } 7624 7625 typedef struct { 7626 PetscInt n; 7627 IS *is; 7628 Mat *mat; 7629 PetscObjectState nonzerostate; 7630 Mat C; 7631 } EnvelopeData; 7632 7633 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7634 { 7635 EnvelopeData *edata = (EnvelopeData *)ptr; 7636 7637 PetscFunctionBegin; 7638 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7639 PetscCall(PetscFree(edata->is)); 7640 PetscCall(PetscFree(edata)); 7641 PetscFunctionReturn(PETSC_SUCCESS); 7642 } 7643 7644 /*@ 7645 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7646 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7647 7648 Collective 7649 7650 Input Parameter: 7651 . mat - the matrix 7652 7653 Level: intermediate 7654 7655 Notes: 7656 There can be zeros within the blocks 7657 7658 The blocks can overlap between processes, including laying on more than two processes 7659 7660 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7661 @*/ 7662 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7663 { 7664 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7665 PetscInt *diag, *odiag, sc; 7666 VecScatter scatter; 7667 PetscScalar *seqv; 7668 const PetscScalar *parv; 7669 const PetscInt *ia, *ja; 7670 PetscBool set, flag, done; 7671 Mat AA = mat, A; 7672 MPI_Comm comm; 7673 PetscMPIInt rank, size, tag; 7674 MPI_Status status; 7675 PetscContainer container; 7676 EnvelopeData *edata; 7677 Vec seq, par; 7678 IS isglobal; 7679 7680 PetscFunctionBegin; 7681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7682 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7683 if (!set || !flag) { 7684 /* TODO: only needs nonzero structure of transpose */ 7685 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7686 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7687 } 7688 PetscCall(MatAIJGetLocalMat(AA, &A)); 7689 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7690 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7691 7692 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7693 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7694 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7695 PetscCallMPI(MPI_Comm_size(comm, &size)); 7696 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7697 7698 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7699 7700 if (rank > 0) { 7701 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7702 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7703 } 7704 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7705 for (i = 0; i < n; i++) { 7706 env = PetscMax(env, ja[ia[i + 1] - 1]); 7707 II = rstart + i; 7708 if (env == II) { 7709 starts[lblocks] = tbs; 7710 sizes[lblocks++] = 1 + II - tbs; 7711 tbs = 1 + II; 7712 } 7713 } 7714 if (rank < size - 1) { 7715 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7716 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7717 } 7718 7719 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7720 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7721 PetscCall(MatDestroy(&A)); 7722 7723 PetscCall(PetscNew(&edata)); 7724 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7725 edata->n = lblocks; 7726 /* create IS needed for extracting blocks from the original matrix */ 7727 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7728 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7729 7730 /* Create the resulting inverse matrix structure with preallocation information */ 7731 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7732 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7733 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7734 PetscCall(MatSetType(edata->C, MATAIJ)); 7735 7736 /* Communicate the start and end of each row, from each block to the correct rank */ 7737 /* TODO: Use PetscSF instead of VecScatter */ 7738 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7739 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7740 PetscCall(VecGetArrayWrite(seq, &seqv)); 7741 for (PetscInt i = 0; i < lblocks; i++) { 7742 for (PetscInt j = 0; j < sizes[i]; j++) { 7743 seqv[cnt] = starts[i]; 7744 seqv[cnt + 1] = starts[i] + sizes[i]; 7745 cnt += 2; 7746 } 7747 } 7748 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7749 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7750 sc -= cnt; 7751 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7752 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7753 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7754 PetscCall(ISDestroy(&isglobal)); 7755 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7756 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7757 PetscCall(VecScatterDestroy(&scatter)); 7758 PetscCall(VecDestroy(&seq)); 7759 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7760 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7761 PetscCall(VecGetArrayRead(par, &parv)); 7762 cnt = 0; 7763 PetscCall(MatGetSize(mat, NULL, &n)); 7764 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7765 PetscInt start, end, d = 0, od = 0; 7766 7767 start = (PetscInt)PetscRealPart(parv[cnt]); 7768 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7769 cnt += 2; 7770 7771 if (start < cstart) { 7772 od += cstart - start + n - cend; 7773 d += cend - cstart; 7774 } else if (start < cend) { 7775 od += n - cend; 7776 d += cend - start; 7777 } else od += n - start; 7778 if (end <= cstart) { 7779 od -= cstart - end + n - cend; 7780 d -= cend - cstart; 7781 } else if (end < cend) { 7782 od -= n - cend; 7783 d -= cend - end; 7784 } else od -= n - end; 7785 7786 odiag[i] = od; 7787 diag[i] = d; 7788 } 7789 PetscCall(VecRestoreArrayRead(par, &parv)); 7790 PetscCall(VecDestroy(&par)); 7791 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7792 PetscCall(PetscFree2(diag, odiag)); 7793 PetscCall(PetscFree2(sizes, starts)); 7794 7795 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7796 PetscCall(PetscContainerSetPointer(container, edata)); 7797 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7798 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7799 PetscCall(PetscObjectDereference((PetscObject)container)); 7800 PetscFunctionReturn(PETSC_SUCCESS); 7801 } 7802 7803 /*@ 7804 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7805 7806 Collective 7807 7808 Input Parameters: 7809 + A - the matrix 7810 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7811 7812 Output Parameter: 7813 . C - matrix with inverted block diagonal of `A` 7814 7815 Level: advanced 7816 7817 Note: 7818 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7819 7820 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7821 @*/ 7822 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7823 { 7824 PetscContainer container; 7825 EnvelopeData *edata; 7826 PetscObjectState nonzerostate; 7827 7828 PetscFunctionBegin; 7829 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7830 if (!container) { 7831 PetscCall(MatComputeVariableBlockEnvelope(A)); 7832 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7833 } 7834 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7835 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7836 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7837 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7838 7839 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7840 *C = edata->C; 7841 7842 for (PetscInt i = 0; i < edata->n; i++) { 7843 Mat D; 7844 PetscScalar *dvalues; 7845 7846 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7847 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7848 PetscCall(MatSeqDenseInvert(D)); 7849 PetscCall(MatDenseGetArray(D, &dvalues)); 7850 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7851 PetscCall(MatDestroy(&D)); 7852 } 7853 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7854 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7855 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7856 PetscFunctionReturn(PETSC_SUCCESS); 7857 } 7858 7859 /*@ 7860 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7861 7862 Not Collective 7863 7864 Input Parameters: 7865 + mat - the matrix 7866 . nblocks - the number of blocks on this process, each block can only exist on a single process 7867 - bsizes - the block sizes 7868 7869 Level: intermediate 7870 7871 Notes: 7872 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7873 7874 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. 7875 7876 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7877 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7878 @*/ 7879 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7880 { 7881 PetscInt ncnt = 0, nlocal; 7882 7883 PetscFunctionBegin; 7884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7885 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7886 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); 7887 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7888 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); 7889 PetscCall(PetscFree(mat->bsizes)); 7890 mat->nblocks = nblocks; 7891 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7892 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7893 PetscFunctionReturn(PETSC_SUCCESS); 7894 } 7895 7896 /*@C 7897 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7898 7899 Not Collective; No Fortran Support 7900 7901 Input Parameter: 7902 . mat - the matrix 7903 7904 Output Parameters: 7905 + nblocks - the number of blocks on this process 7906 - bsizes - the block sizes 7907 7908 Level: intermediate 7909 7910 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7911 @*/ 7912 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7913 { 7914 PetscFunctionBegin; 7915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7916 if (nblocks) *nblocks = mat->nblocks; 7917 if (bsizes) *bsizes = mat->bsizes; 7918 PetscFunctionReturn(PETSC_SUCCESS); 7919 } 7920 7921 /*@ 7922 MatSetBlockSizes - Sets the matrix block row and column sizes. 7923 7924 Logically Collective 7925 7926 Input Parameters: 7927 + mat - the matrix 7928 . rbs - row block size 7929 - cbs - column block size 7930 7931 Level: intermediate 7932 7933 Notes: 7934 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7935 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7936 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7937 7938 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7939 are compatible with the matrix local sizes. 7940 7941 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7942 7943 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7944 @*/ 7945 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7946 { 7947 PetscFunctionBegin; 7948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7949 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7950 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7951 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7952 if (mat->rmap->refcnt) { 7953 ISLocalToGlobalMapping l2g = NULL; 7954 PetscLayout nmap = NULL; 7955 7956 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7957 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7958 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7959 mat->rmap = nmap; 7960 mat->rmap->mapping = l2g; 7961 } 7962 if (mat->cmap->refcnt) { 7963 ISLocalToGlobalMapping l2g = NULL; 7964 PetscLayout nmap = NULL; 7965 7966 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7967 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7968 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7969 mat->cmap = nmap; 7970 mat->cmap->mapping = l2g; 7971 } 7972 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7973 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7974 PetscFunctionReturn(PETSC_SUCCESS); 7975 } 7976 7977 /*@ 7978 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7979 7980 Logically Collective 7981 7982 Input Parameters: 7983 + mat - the matrix 7984 . fromRow - matrix from which to copy row block size 7985 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7986 7987 Level: developer 7988 7989 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7990 @*/ 7991 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7992 { 7993 PetscFunctionBegin; 7994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7995 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7996 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7997 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7998 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7999 PetscFunctionReturn(PETSC_SUCCESS); 8000 } 8001 8002 /*@ 8003 MatResidual - Default routine to calculate the residual r = b - Ax 8004 8005 Collective 8006 8007 Input Parameters: 8008 + mat - the matrix 8009 . b - the right-hand-side 8010 - x - the approximate solution 8011 8012 Output Parameter: 8013 . r - location to store the residual 8014 8015 Level: developer 8016 8017 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8018 @*/ 8019 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8020 { 8021 PetscFunctionBegin; 8022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8023 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8024 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8025 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8026 PetscValidType(mat, 1); 8027 MatCheckPreallocated(mat, 1); 8028 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8029 if (!mat->ops->residual) { 8030 PetscCall(MatMult(mat, x, r)); 8031 PetscCall(VecAYPX(r, -1.0, b)); 8032 } else { 8033 PetscUseTypeMethod(mat, residual, b, x, r); 8034 } 8035 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8036 PetscFunctionReturn(PETSC_SUCCESS); 8037 } 8038 8039 /*MC 8040 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8041 8042 Synopsis: 8043 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8044 8045 Not Collective 8046 8047 Input Parameters: 8048 + A - the matrix 8049 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8050 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8051 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8052 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8053 always used. 8054 8055 Output Parameters: 8056 + n - number of local rows in the (possibly compressed) matrix 8057 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8058 . ja - the column indices 8059 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8060 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8061 8062 Level: developer 8063 8064 Note: 8065 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8066 8067 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8068 M*/ 8069 8070 /*MC 8071 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8072 8073 Synopsis: 8074 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8075 8076 Not Collective 8077 8078 Input Parameters: 8079 + A - the matrix 8080 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8081 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8082 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8083 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8084 always used. 8085 . n - number of local rows in the (possibly compressed) matrix 8086 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8087 . ja - the column indices 8088 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8089 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8090 8091 Level: developer 8092 8093 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8094 M*/ 8095 8096 /*@C 8097 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8098 8099 Collective 8100 8101 Input Parameters: 8102 + mat - the matrix 8103 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8104 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8105 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8106 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8107 always used. 8108 8109 Output Parameters: 8110 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8111 . 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 8112 . ja - the column indices, use `NULL` if not needed 8113 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8114 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8115 8116 Level: developer 8117 8118 Notes: 8119 You CANNOT change any of the ia[] or ja[] values. 8120 8121 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8122 8123 Fortran Notes: 8124 Use 8125 .vb 8126 PetscInt, pointer :: ia(:),ja(:) 8127 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8128 ! Access the ith and jth entries via ia(i) and ja(j) 8129 .ve 8130 8131 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8132 8133 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8134 @*/ 8135 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8136 { 8137 PetscFunctionBegin; 8138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8139 PetscValidType(mat, 1); 8140 if (n) PetscAssertPointer(n, 5); 8141 if (ia) PetscAssertPointer(ia, 6); 8142 if (ja) PetscAssertPointer(ja, 7); 8143 if (done) PetscAssertPointer(done, 8); 8144 MatCheckPreallocated(mat, 1); 8145 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8146 else { 8147 if (done) *done = PETSC_TRUE; 8148 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8149 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8150 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8151 } 8152 PetscFunctionReturn(PETSC_SUCCESS); 8153 } 8154 8155 /*@C 8156 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8157 8158 Collective 8159 8160 Input Parameters: 8161 + mat - the matrix 8162 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8163 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8164 symmetrized 8165 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8166 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8167 always used. 8168 . n - number of columns in the (possibly compressed) matrix 8169 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8170 - ja - the row indices 8171 8172 Output Parameter: 8173 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8174 8175 Level: developer 8176 8177 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8178 @*/ 8179 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8180 { 8181 PetscFunctionBegin; 8182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8183 PetscValidType(mat, 1); 8184 PetscAssertPointer(n, 5); 8185 if (ia) PetscAssertPointer(ia, 6); 8186 if (ja) PetscAssertPointer(ja, 7); 8187 PetscAssertPointer(done, 8); 8188 MatCheckPreallocated(mat, 1); 8189 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8190 else { 8191 *done = PETSC_TRUE; 8192 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8193 } 8194 PetscFunctionReturn(PETSC_SUCCESS); 8195 } 8196 8197 /*@C 8198 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8199 8200 Collective 8201 8202 Input Parameters: 8203 + mat - the matrix 8204 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8205 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8206 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8207 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8208 always used. 8209 . n - size of (possibly compressed) matrix 8210 . ia - the row pointers 8211 - ja - the column indices 8212 8213 Output Parameter: 8214 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8215 8216 Level: developer 8217 8218 Note: 8219 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8220 us of the array after it has been restored. If you pass `NULL`, it will 8221 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8222 8223 Fortran Note: 8224 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8225 8226 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8227 @*/ 8228 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8229 { 8230 PetscFunctionBegin; 8231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8232 PetscValidType(mat, 1); 8233 if (ia) PetscAssertPointer(ia, 6); 8234 if (ja) PetscAssertPointer(ja, 7); 8235 if (done) PetscAssertPointer(done, 8); 8236 MatCheckPreallocated(mat, 1); 8237 8238 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8239 else { 8240 if (done) *done = PETSC_TRUE; 8241 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8242 if (n) *n = 0; 8243 if (ia) *ia = NULL; 8244 if (ja) *ja = NULL; 8245 } 8246 PetscFunctionReturn(PETSC_SUCCESS); 8247 } 8248 8249 /*@C 8250 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8251 8252 Collective 8253 8254 Input Parameters: 8255 + mat - the matrix 8256 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8257 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8258 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8259 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8260 always used. 8261 8262 Output Parameters: 8263 + n - size of (possibly compressed) matrix 8264 . ia - the column pointers 8265 . ja - the row indices 8266 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8267 8268 Level: developer 8269 8270 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8271 @*/ 8272 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8273 { 8274 PetscFunctionBegin; 8275 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8276 PetscValidType(mat, 1); 8277 if (ia) PetscAssertPointer(ia, 6); 8278 if (ja) PetscAssertPointer(ja, 7); 8279 PetscAssertPointer(done, 8); 8280 MatCheckPreallocated(mat, 1); 8281 8282 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8283 else { 8284 *done = PETSC_TRUE; 8285 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8286 if (n) *n = 0; 8287 if (ia) *ia = NULL; 8288 if (ja) *ja = NULL; 8289 } 8290 PetscFunctionReturn(PETSC_SUCCESS); 8291 } 8292 8293 /*@ 8294 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8295 `MatGetColumnIJ()`. 8296 8297 Collective 8298 8299 Input Parameters: 8300 + mat - the matrix 8301 . ncolors - maximum color value 8302 . n - number of entries in colorarray 8303 - colorarray - array indicating color for each column 8304 8305 Output Parameter: 8306 . iscoloring - coloring generated using colorarray information 8307 8308 Level: developer 8309 8310 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8311 @*/ 8312 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8313 { 8314 PetscFunctionBegin; 8315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8316 PetscValidType(mat, 1); 8317 PetscAssertPointer(colorarray, 4); 8318 PetscAssertPointer(iscoloring, 5); 8319 MatCheckPreallocated(mat, 1); 8320 8321 if (!mat->ops->coloringpatch) { 8322 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8323 } else { 8324 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8325 } 8326 PetscFunctionReturn(PETSC_SUCCESS); 8327 } 8328 8329 /*@ 8330 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8331 8332 Logically Collective 8333 8334 Input Parameter: 8335 . mat - the factored matrix to be reset 8336 8337 Level: developer 8338 8339 Notes: 8340 This routine should be used only with factored matrices formed by in-place 8341 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8342 format). This option can save memory, for example, when solving nonlinear 8343 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8344 ILU(0) preconditioner. 8345 8346 One can specify in-place ILU(0) factorization by calling 8347 .vb 8348 PCType(pc,PCILU); 8349 PCFactorSeUseInPlace(pc); 8350 .ve 8351 or by using the options -pc_type ilu -pc_factor_in_place 8352 8353 In-place factorization ILU(0) can also be used as a local 8354 solver for the blocks within the block Jacobi or additive Schwarz 8355 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8356 for details on setting local solver options. 8357 8358 Most users should employ the `KSP` interface for linear solvers 8359 instead of working directly with matrix algebra routines such as this. 8360 See, e.g., `KSPCreate()`. 8361 8362 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8363 @*/ 8364 PetscErrorCode MatSetUnfactored(Mat mat) 8365 { 8366 PetscFunctionBegin; 8367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8368 PetscValidType(mat, 1); 8369 MatCheckPreallocated(mat, 1); 8370 mat->factortype = MAT_FACTOR_NONE; 8371 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8372 PetscUseTypeMethod(mat, setunfactored); 8373 PetscFunctionReturn(PETSC_SUCCESS); 8374 } 8375 8376 /*MC 8377 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8378 8379 Synopsis: 8380 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8381 8382 Not Collective 8383 8384 Input Parameter: 8385 . x - matrix 8386 8387 Output Parameters: 8388 + xx_v - the Fortran pointer to the array 8389 - ierr - error code 8390 8391 Example of Usage: 8392 .vb 8393 PetscScalar, pointer xx_v(:,:) 8394 .... 8395 call MatDenseGetArrayF90(x,xx_v,ierr) 8396 a = xx_v(3) 8397 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8398 .ve 8399 8400 Level: advanced 8401 8402 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8403 M*/ 8404 8405 /*MC 8406 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8407 accessed with `MatDenseGetArrayF90()`. 8408 8409 Synopsis: 8410 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8411 8412 Not Collective 8413 8414 Input Parameters: 8415 + x - matrix 8416 - xx_v - the Fortran90 pointer to the array 8417 8418 Output Parameter: 8419 . ierr - error code 8420 8421 Example of Usage: 8422 .vb 8423 PetscScalar, pointer xx_v(:,:) 8424 .... 8425 call MatDenseGetArrayF90(x,xx_v,ierr) 8426 a = xx_v(3) 8427 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8428 .ve 8429 8430 Level: advanced 8431 8432 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8433 M*/ 8434 8435 /*MC 8436 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8437 8438 Synopsis: 8439 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8440 8441 Not Collective 8442 8443 Input Parameter: 8444 . x - matrix 8445 8446 Output Parameters: 8447 + xx_v - the Fortran pointer to the array 8448 - ierr - error code 8449 8450 Example of Usage: 8451 .vb 8452 PetscScalar, pointer xx_v(:) 8453 .... 8454 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8455 a = xx_v(3) 8456 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8457 .ve 8458 8459 Level: advanced 8460 8461 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8462 M*/ 8463 8464 /*MC 8465 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8466 accessed with `MatSeqAIJGetArrayF90()`. 8467 8468 Synopsis: 8469 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8470 8471 Not Collective 8472 8473 Input Parameters: 8474 + x - matrix 8475 - xx_v - the Fortran90 pointer to the array 8476 8477 Output Parameter: 8478 . ierr - error code 8479 8480 Example of Usage: 8481 .vb 8482 PetscScalar, pointer xx_v(:) 8483 .... 8484 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8485 a = xx_v(3) 8486 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8487 .ve 8488 8489 Level: advanced 8490 8491 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8492 M*/ 8493 8494 /*@ 8495 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8496 as the original matrix. 8497 8498 Collective 8499 8500 Input Parameters: 8501 + mat - the original matrix 8502 . isrow - parallel `IS` containing the rows this processor should obtain 8503 . 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. 8504 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8505 8506 Output Parameter: 8507 . newmat - the new submatrix, of the same type as the original matrix 8508 8509 Level: advanced 8510 8511 Notes: 8512 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8513 8514 Some matrix types place restrictions on the row and column indices, such 8515 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; 8516 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8517 8518 The index sets may not have duplicate entries. 8519 8520 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8521 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8522 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8523 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8524 you are finished using it. 8525 8526 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8527 the input matrix. 8528 8529 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8530 8531 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8532 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8533 8534 Example usage: 8535 Consider the following 8x8 matrix with 34 non-zero values, that is 8536 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8537 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8538 as follows 8539 .vb 8540 1 2 0 | 0 3 0 | 0 4 8541 Proc0 0 5 6 | 7 0 0 | 8 0 8542 9 0 10 | 11 0 0 | 12 0 8543 ------------------------------------- 8544 13 0 14 | 15 16 17 | 0 0 8545 Proc1 0 18 0 | 19 20 21 | 0 0 8546 0 0 0 | 22 23 0 | 24 0 8547 ------------------------------------- 8548 Proc2 25 26 27 | 0 0 28 | 29 0 8549 30 0 0 | 31 32 33 | 0 34 8550 .ve 8551 8552 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8553 8554 .vb 8555 2 0 | 0 3 0 | 0 8556 Proc0 5 6 | 7 0 0 | 8 8557 ------------------------------- 8558 Proc1 18 0 | 19 20 21 | 0 8559 ------------------------------- 8560 Proc2 26 27 | 0 0 28 | 29 8561 0 0 | 31 32 33 | 0 8562 .ve 8563 8564 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8565 @*/ 8566 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8567 { 8568 PetscMPIInt size; 8569 Mat *local; 8570 IS iscoltmp; 8571 PetscBool flg; 8572 8573 PetscFunctionBegin; 8574 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8575 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8576 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8577 PetscAssertPointer(newmat, 5); 8578 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8579 PetscValidType(mat, 1); 8580 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8581 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8582 8583 MatCheckPreallocated(mat, 1); 8584 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8585 8586 if (!iscol || isrow == iscol) { 8587 PetscBool stride; 8588 PetscMPIInt grabentirematrix = 0, grab; 8589 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8590 if (stride) { 8591 PetscInt first, step, n, rstart, rend; 8592 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8593 if (step == 1) { 8594 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8595 if (rstart == first) { 8596 PetscCall(ISGetLocalSize(isrow, &n)); 8597 if (n == rend - rstart) grabentirematrix = 1; 8598 } 8599 } 8600 } 8601 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8602 if (grab) { 8603 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8604 if (cll == MAT_INITIAL_MATRIX) { 8605 *newmat = mat; 8606 PetscCall(PetscObjectReference((PetscObject)mat)); 8607 } 8608 PetscFunctionReturn(PETSC_SUCCESS); 8609 } 8610 } 8611 8612 if (!iscol) { 8613 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8614 } else { 8615 iscoltmp = iscol; 8616 } 8617 8618 /* if original matrix is on just one processor then use submatrix generated */ 8619 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8620 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8621 goto setproperties; 8622 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8623 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8624 *newmat = *local; 8625 PetscCall(PetscFree(local)); 8626 goto setproperties; 8627 } else if (!mat->ops->createsubmatrix) { 8628 /* Create a new matrix type that implements the operation using the full matrix */ 8629 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8630 switch (cll) { 8631 case MAT_INITIAL_MATRIX: 8632 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8633 break; 8634 case MAT_REUSE_MATRIX: 8635 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8636 break; 8637 default: 8638 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8639 } 8640 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8641 goto setproperties; 8642 } 8643 8644 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8645 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8646 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8647 8648 setproperties: 8649 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8650 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8651 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8652 } 8653 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8654 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8655 PetscFunctionReturn(PETSC_SUCCESS); 8656 } 8657 8658 /*@ 8659 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8660 8661 Not Collective 8662 8663 Input Parameters: 8664 + A - the matrix we wish to propagate options from 8665 - B - the matrix we wish to propagate options to 8666 8667 Level: beginner 8668 8669 Note: 8670 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8671 8672 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8673 @*/ 8674 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8675 { 8676 PetscFunctionBegin; 8677 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8678 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8679 B->symmetry_eternal = A->symmetry_eternal; 8680 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8681 B->symmetric = A->symmetric; 8682 B->structurally_symmetric = A->structurally_symmetric; 8683 B->spd = A->spd; 8684 B->hermitian = A->hermitian; 8685 PetscFunctionReturn(PETSC_SUCCESS); 8686 } 8687 8688 /*@ 8689 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8690 used during the assembly process to store values that belong to 8691 other processors. 8692 8693 Not Collective 8694 8695 Input Parameters: 8696 + mat - the matrix 8697 . size - the initial size of the stash. 8698 - bsize - the initial size of the block-stash(if used). 8699 8700 Options Database Keys: 8701 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8702 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8703 8704 Level: intermediate 8705 8706 Notes: 8707 The block-stash is used for values set with `MatSetValuesBlocked()` while 8708 the stash is used for values set with `MatSetValues()` 8709 8710 Run with the option -info and look for output of the form 8711 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8712 to determine the appropriate value, MM, to use for size and 8713 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8714 to determine the value, BMM to use for bsize 8715 8716 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8717 @*/ 8718 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8719 { 8720 PetscFunctionBegin; 8721 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8722 PetscValidType(mat, 1); 8723 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8724 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8725 PetscFunctionReturn(PETSC_SUCCESS); 8726 } 8727 8728 /*@ 8729 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8730 the matrix 8731 8732 Neighbor-wise Collective 8733 8734 Input Parameters: 8735 + A - the matrix 8736 . x - the vector to be multiplied by the interpolation operator 8737 - y - the vector to be added to the result 8738 8739 Output Parameter: 8740 . w - the resulting vector 8741 8742 Level: intermediate 8743 8744 Notes: 8745 `w` may be the same vector as `y`. 8746 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 MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 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 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8761 PetscCall(MatGetSize(A, &M, &N)); 8762 PetscCall(VecGetSize(y, &Ny)); 8763 if (M == Ny) { 8764 PetscCall(MatMultAdd(A, x, y, w)); 8765 } else { 8766 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8767 } 8768 PetscFunctionReturn(PETSC_SUCCESS); 8769 } 8770 8771 /*@ 8772 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8773 the matrix 8774 8775 Neighbor-wise Collective 8776 8777 Input Parameters: 8778 + A - the matrix 8779 - x - the vector to be interpolated 8780 8781 Output Parameter: 8782 . y - the resulting vector 8783 8784 Level: intermediate 8785 8786 Note: 8787 This allows one to use either the restriction or interpolation (its transpose) 8788 matrix to do the interpolation 8789 8790 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8791 @*/ 8792 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8793 { 8794 PetscInt M, N, Ny; 8795 8796 PetscFunctionBegin; 8797 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8798 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8799 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8800 PetscCall(MatGetSize(A, &M, &N)); 8801 PetscCall(VecGetSize(y, &Ny)); 8802 if (M == Ny) { 8803 PetscCall(MatMult(A, x, y)); 8804 } else { 8805 PetscCall(MatMultTranspose(A, x, y)); 8806 } 8807 PetscFunctionReturn(PETSC_SUCCESS); 8808 } 8809 8810 /*@ 8811 MatRestrict - $y = A*x$ or $A^T*x$ 8812 8813 Neighbor-wise Collective 8814 8815 Input Parameters: 8816 + A - the matrix 8817 - x - the vector to be restricted 8818 8819 Output Parameter: 8820 . y - the resulting vector 8821 8822 Level: intermediate 8823 8824 Note: 8825 This allows one to use either the restriction or interpolation (its transpose) 8826 matrix to do the restriction 8827 8828 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8829 @*/ 8830 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8831 { 8832 PetscInt M, N, Nx; 8833 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8836 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8837 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8838 PetscCall(MatGetSize(A, &M, &N)); 8839 PetscCall(VecGetSize(x, &Nx)); 8840 if (M == Nx) { 8841 PetscCall(MatMultTranspose(A, x, y)); 8842 } else { 8843 PetscCall(MatMult(A, x, y)); 8844 } 8845 PetscFunctionReturn(PETSC_SUCCESS); 8846 } 8847 8848 /*@ 8849 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8850 8851 Neighbor-wise Collective 8852 8853 Input Parameters: 8854 + A - the matrix 8855 . x - the input dense matrix to be multiplied 8856 - w - the input dense matrix to be added to the result 8857 8858 Output Parameter: 8859 . y - the output dense matrix 8860 8861 Level: intermediate 8862 8863 Note: 8864 This allows one to use either the restriction or interpolation (its transpose) 8865 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8866 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8867 8868 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8869 @*/ 8870 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8871 { 8872 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8873 PetscBool trans = PETSC_TRUE; 8874 MatReuse reuse = MAT_INITIAL_MATRIX; 8875 8876 PetscFunctionBegin; 8877 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8878 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8879 PetscValidType(x, 2); 8880 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8881 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8882 PetscCall(MatGetSize(A, &M, &N)); 8883 PetscCall(MatGetSize(x, &Mx, &Nx)); 8884 if (N == Mx) trans = PETSC_FALSE; 8885 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); 8886 Mo = trans ? N : M; 8887 if (*y) { 8888 PetscCall(MatGetSize(*y, &My, &Ny)); 8889 if (Mo == My && Nx == Ny) { 8890 reuse = MAT_REUSE_MATRIX; 8891 } else { 8892 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); 8893 PetscCall(MatDestroy(y)); 8894 } 8895 } 8896 8897 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8898 PetscBool flg; 8899 8900 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8901 if (w) { 8902 PetscInt My, Ny, Mw, Nw; 8903 8904 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8905 PetscCall(MatGetSize(*y, &My, &Ny)); 8906 PetscCall(MatGetSize(w, &Mw, &Nw)); 8907 if (!flg || My != Mw || Ny != Nw) w = NULL; 8908 } 8909 if (!w) { 8910 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8911 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8912 PetscCall(PetscObjectDereference((PetscObject)w)); 8913 } else { 8914 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8915 } 8916 } 8917 if (!trans) { 8918 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8919 } else { 8920 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8921 } 8922 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8923 PetscFunctionReturn(PETSC_SUCCESS); 8924 } 8925 8926 /*@ 8927 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8928 8929 Neighbor-wise Collective 8930 8931 Input Parameters: 8932 + A - the matrix 8933 - x - the input dense matrix 8934 8935 Output Parameter: 8936 . y - the output dense matrix 8937 8938 Level: intermediate 8939 8940 Note: 8941 This allows one to use either the restriction or interpolation (its transpose) 8942 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8943 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8944 8945 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8946 @*/ 8947 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8948 { 8949 PetscFunctionBegin; 8950 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8951 PetscFunctionReturn(PETSC_SUCCESS); 8952 } 8953 8954 /*@ 8955 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8956 8957 Neighbor-wise Collective 8958 8959 Input Parameters: 8960 + A - the matrix 8961 - x - the input dense matrix 8962 8963 Output Parameter: 8964 . y - the output dense matrix 8965 8966 Level: intermediate 8967 8968 Note: 8969 This allows one to use either the restriction or interpolation (its transpose) 8970 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8971 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8972 8973 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8974 @*/ 8975 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8976 { 8977 PetscFunctionBegin; 8978 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8979 PetscFunctionReturn(PETSC_SUCCESS); 8980 } 8981 8982 /*@ 8983 MatGetNullSpace - retrieves the null space of a matrix. 8984 8985 Logically Collective 8986 8987 Input Parameters: 8988 + mat - the matrix 8989 - nullsp - the null space object 8990 8991 Level: developer 8992 8993 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8994 @*/ 8995 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8996 { 8997 PetscFunctionBegin; 8998 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8999 PetscAssertPointer(nullsp, 2); 9000 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 9001 PetscFunctionReturn(PETSC_SUCCESS); 9002 } 9003 9004 /*@C 9005 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from 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 9013 Output Parameters: 9014 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9015 9016 Level: developer 9017 9018 Note: 9019 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9020 9021 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9022 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9023 @*/ 9024 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9025 { 9026 PetscFunctionBegin; 9027 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9028 PetscAssertPointer(mat, 2); 9029 PetscAssertPointer(nullsp, 3); 9030 9031 PetscCall(PetscCalloc1(3 * n, nullsp)); 9032 for (PetscInt i = 0; i < n; i++) { 9033 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9034 (*nullsp)[i] = mat[i]->nullsp; 9035 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9036 (*nullsp)[n + i] = mat[i]->nearnullsp; 9037 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9038 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9039 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9040 } 9041 PetscFunctionReturn(PETSC_SUCCESS); 9042 } 9043 9044 /*@C 9045 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9046 9047 Logically Collective 9048 9049 Input Parameters: 9050 + n - the number of matrices 9051 . mat - the array of matrices 9052 - nullsp - an array of null spaces 9053 9054 Level: developer 9055 9056 Note: 9057 Call `MatGetNullSpaces()` to create `nullsp` 9058 9059 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9060 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9061 @*/ 9062 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9063 { 9064 PetscFunctionBegin; 9065 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9066 PetscAssertPointer(mat, 2); 9067 PetscAssertPointer(nullsp, 3); 9068 PetscAssertPointer(*nullsp, 3); 9069 9070 for (PetscInt i = 0; i < n; i++) { 9071 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9072 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9073 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9074 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9075 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9076 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9077 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9078 } 9079 PetscCall(PetscFree(*nullsp)); 9080 PetscFunctionReturn(PETSC_SUCCESS); 9081 } 9082 9083 /*@ 9084 MatSetNullSpace - attaches a null space to a matrix. 9085 9086 Logically Collective 9087 9088 Input Parameters: 9089 + mat - the matrix 9090 - nullsp - the null space object 9091 9092 Level: advanced 9093 9094 Notes: 9095 This null space is used by the `KSP` linear solvers to solve singular systems. 9096 9097 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` 9098 9099 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 9100 to zero but the linear system will still be solved in a least squares sense. 9101 9102 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9103 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)$. 9104 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 9105 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 9106 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$). 9107 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9108 9109 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9110 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9111 routine also automatically calls `MatSetTransposeNullSpace()`. 9112 9113 The user should call `MatNullSpaceDestroy()`. 9114 9115 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9116 `KSPSetPCSide()` 9117 @*/ 9118 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9119 { 9120 PetscFunctionBegin; 9121 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9122 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9123 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9124 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9125 mat->nullsp = nullsp; 9126 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9127 PetscFunctionReturn(PETSC_SUCCESS); 9128 } 9129 9130 /*@ 9131 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9132 9133 Logically Collective 9134 9135 Input Parameters: 9136 + mat - the matrix 9137 - nullsp - the null space object 9138 9139 Level: developer 9140 9141 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9142 @*/ 9143 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9144 { 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9147 PetscValidType(mat, 1); 9148 PetscAssertPointer(nullsp, 2); 9149 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9150 PetscFunctionReturn(PETSC_SUCCESS); 9151 } 9152 9153 /*@ 9154 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9155 9156 Logically Collective 9157 9158 Input Parameters: 9159 + mat - the matrix 9160 - nullsp - the null space object 9161 9162 Level: advanced 9163 9164 Notes: 9165 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9166 9167 See `MatSetNullSpace()` 9168 9169 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9170 @*/ 9171 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9172 { 9173 PetscFunctionBegin; 9174 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9175 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9176 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9177 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9178 mat->transnullsp = nullsp; 9179 PetscFunctionReturn(PETSC_SUCCESS); 9180 } 9181 9182 /*@ 9183 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9184 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9185 9186 Logically Collective 9187 9188 Input Parameters: 9189 + mat - the matrix 9190 - nullsp - the null space object 9191 9192 Level: advanced 9193 9194 Notes: 9195 Overwrites any previous near null space that may have been attached 9196 9197 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9198 9199 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9200 @*/ 9201 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9202 { 9203 PetscFunctionBegin; 9204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9205 PetscValidType(mat, 1); 9206 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9207 MatCheckPreallocated(mat, 1); 9208 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9209 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9210 mat->nearnullsp = nullsp; 9211 PetscFunctionReturn(PETSC_SUCCESS); 9212 } 9213 9214 /*@ 9215 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9216 9217 Not Collective 9218 9219 Input Parameter: 9220 . mat - the matrix 9221 9222 Output Parameter: 9223 . nullsp - the null space object, `NULL` if not set 9224 9225 Level: advanced 9226 9227 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9228 @*/ 9229 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9230 { 9231 PetscFunctionBegin; 9232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9233 PetscValidType(mat, 1); 9234 PetscAssertPointer(nullsp, 2); 9235 MatCheckPreallocated(mat, 1); 9236 *nullsp = mat->nearnullsp; 9237 PetscFunctionReturn(PETSC_SUCCESS); 9238 } 9239 9240 /*@ 9241 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9242 9243 Collective 9244 9245 Input Parameters: 9246 + mat - the matrix 9247 . row - row/column permutation 9248 - info - information on desired factorization process 9249 9250 Level: developer 9251 9252 Notes: 9253 Probably really in-place only when level of fill is zero, otherwise allocates 9254 new space to store factored matrix and deletes previous memory. 9255 9256 Most users should employ the `KSP` interface for linear solvers 9257 instead of working directly with matrix algebra routines such as this. 9258 See, e.g., `KSPCreate()`. 9259 9260 Developer Note: 9261 The Fortran interface is not autogenerated as the 9262 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9263 9264 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9265 @*/ 9266 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9267 { 9268 PetscFunctionBegin; 9269 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9270 PetscValidType(mat, 1); 9271 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9272 PetscAssertPointer(info, 3); 9273 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9276 MatCheckPreallocated(mat, 1); 9277 PetscUseTypeMethod(mat, iccfactor, row, info); 9278 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9279 PetscFunctionReturn(PETSC_SUCCESS); 9280 } 9281 9282 /*@ 9283 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9284 ghosted ones. 9285 9286 Not Collective 9287 9288 Input Parameters: 9289 + mat - the matrix 9290 - diag - the diagonal values, including ghost ones 9291 9292 Level: developer 9293 9294 Notes: 9295 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9296 9297 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9298 9299 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9300 @*/ 9301 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9302 { 9303 PetscMPIInt size; 9304 9305 PetscFunctionBegin; 9306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9307 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9308 PetscValidType(mat, 1); 9309 9310 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9311 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9312 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9313 if (size == 1) { 9314 PetscInt n, m; 9315 PetscCall(VecGetSize(diag, &n)); 9316 PetscCall(MatGetSize(mat, NULL, &m)); 9317 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9318 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9319 } else { 9320 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9321 } 9322 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9323 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9324 PetscFunctionReturn(PETSC_SUCCESS); 9325 } 9326 9327 /*@ 9328 MatGetInertia - Gets the inertia from a factored matrix 9329 9330 Collective 9331 9332 Input Parameter: 9333 . mat - the matrix 9334 9335 Output Parameters: 9336 + nneg - number of negative eigenvalues 9337 . nzero - number of zero eigenvalues 9338 - npos - number of positive eigenvalues 9339 9340 Level: advanced 9341 9342 Note: 9343 Matrix must have been factored by `MatCholeskyFactor()` 9344 9345 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9346 @*/ 9347 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9348 { 9349 PetscFunctionBegin; 9350 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9351 PetscValidType(mat, 1); 9352 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9353 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9354 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9355 PetscFunctionReturn(PETSC_SUCCESS); 9356 } 9357 9358 /*@C 9359 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9360 9361 Neighbor-wise Collective 9362 9363 Input Parameters: 9364 + mat - the factored matrix obtained with `MatGetFactor()` 9365 - b - the right-hand-side vectors 9366 9367 Output Parameter: 9368 . x - the result vectors 9369 9370 Level: developer 9371 9372 Note: 9373 The vectors `b` and `x` cannot be the same. I.e., one cannot 9374 call `MatSolves`(A,x,x). 9375 9376 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9377 @*/ 9378 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9379 { 9380 PetscFunctionBegin; 9381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9382 PetscValidType(mat, 1); 9383 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9384 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9385 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9386 9387 MatCheckPreallocated(mat, 1); 9388 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9389 PetscUseTypeMethod(mat, solves, b, x); 9390 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9391 PetscFunctionReturn(PETSC_SUCCESS); 9392 } 9393 9394 /*@ 9395 MatIsSymmetric - Test whether a matrix is symmetric 9396 9397 Collective 9398 9399 Input Parameters: 9400 + A - the matrix to test 9401 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9402 9403 Output Parameter: 9404 . flg - the result 9405 9406 Level: intermediate 9407 9408 Notes: 9409 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9410 9411 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9412 9413 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9414 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9415 9416 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9417 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9418 @*/ 9419 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9420 { 9421 PetscFunctionBegin; 9422 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9423 PetscAssertPointer(flg, 3); 9424 if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric); 9425 else { 9426 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9427 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9428 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9429 } 9430 PetscFunctionReturn(PETSC_SUCCESS); 9431 } 9432 9433 /*@ 9434 MatIsHermitian - Test whether a matrix is Hermitian 9435 9436 Collective 9437 9438 Input Parameters: 9439 + A - the matrix to test 9440 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9441 9442 Output Parameter: 9443 . flg - the result 9444 9445 Level: intermediate 9446 9447 Notes: 9448 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9449 9450 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9451 9452 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9453 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9454 9455 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9456 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9457 @*/ 9458 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9459 { 9460 PetscFunctionBegin; 9461 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9462 PetscAssertPointer(flg, 3); 9463 if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian); 9464 else { 9465 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9466 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9467 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9468 } 9469 PetscFunctionReturn(PETSC_SUCCESS); 9470 } 9471 9472 /*@ 9473 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9474 9475 Not Collective 9476 9477 Input Parameter: 9478 . A - the matrix to check 9479 9480 Output Parameters: 9481 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9482 - flg - the result (only valid if set is `PETSC_TRUE`) 9483 9484 Level: advanced 9485 9486 Notes: 9487 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9488 if you want it explicitly checked 9489 9490 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9491 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9492 9493 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9494 @*/ 9495 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9496 { 9497 PetscFunctionBegin; 9498 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9499 PetscAssertPointer(set, 2); 9500 PetscAssertPointer(flg, 3); 9501 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9502 *set = PETSC_TRUE; 9503 *flg = PetscBool3ToBool(A->symmetric); 9504 } else { 9505 *set = PETSC_FALSE; 9506 } 9507 PetscFunctionReturn(PETSC_SUCCESS); 9508 } 9509 9510 /*@ 9511 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9512 9513 Not Collective 9514 9515 Input Parameter: 9516 . A - the matrix to check 9517 9518 Output Parameters: 9519 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9520 - flg - the result (only valid if set is `PETSC_TRUE`) 9521 9522 Level: advanced 9523 9524 Notes: 9525 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9526 9527 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9528 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9529 9530 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9531 @*/ 9532 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9533 { 9534 PetscFunctionBegin; 9535 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9536 PetscAssertPointer(set, 2); 9537 PetscAssertPointer(flg, 3); 9538 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9539 *set = PETSC_TRUE; 9540 *flg = PetscBool3ToBool(A->spd); 9541 } else { 9542 *set = PETSC_FALSE; 9543 } 9544 PetscFunctionReturn(PETSC_SUCCESS); 9545 } 9546 9547 /*@ 9548 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9549 9550 Not Collective 9551 9552 Input Parameter: 9553 . A - the matrix to check 9554 9555 Output Parameters: 9556 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9557 - flg - the result (only valid if set is `PETSC_TRUE`) 9558 9559 Level: advanced 9560 9561 Notes: 9562 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9563 if you want it explicitly checked 9564 9565 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9566 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9567 9568 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9569 @*/ 9570 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9571 { 9572 PetscFunctionBegin; 9573 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9574 PetscAssertPointer(set, 2); 9575 PetscAssertPointer(flg, 3); 9576 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9577 *set = PETSC_TRUE; 9578 *flg = PetscBool3ToBool(A->hermitian); 9579 } else { 9580 *set = PETSC_FALSE; 9581 } 9582 PetscFunctionReturn(PETSC_SUCCESS); 9583 } 9584 9585 /*@ 9586 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9587 9588 Collective 9589 9590 Input Parameter: 9591 . A - the matrix to test 9592 9593 Output Parameter: 9594 . flg - the result 9595 9596 Level: intermediate 9597 9598 Notes: 9599 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9600 9601 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 9602 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9603 9604 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9605 @*/ 9606 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9607 { 9608 PetscFunctionBegin; 9609 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9610 PetscAssertPointer(flg, 2); 9611 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9612 *flg = PetscBool3ToBool(A->structurally_symmetric); 9613 } else { 9614 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9615 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9616 } 9617 PetscFunctionReturn(PETSC_SUCCESS); 9618 } 9619 9620 /*@ 9621 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9622 9623 Not Collective 9624 9625 Input Parameter: 9626 . A - the matrix to check 9627 9628 Output Parameters: 9629 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9630 - flg - the result (only valid if set is PETSC_TRUE) 9631 9632 Level: advanced 9633 9634 Notes: 9635 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 9636 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9637 9638 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9639 9640 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9641 @*/ 9642 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9643 { 9644 PetscFunctionBegin; 9645 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9646 PetscAssertPointer(set, 2); 9647 PetscAssertPointer(flg, 3); 9648 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9649 *set = PETSC_TRUE; 9650 *flg = PetscBool3ToBool(A->structurally_symmetric); 9651 } else { 9652 *set = PETSC_FALSE; 9653 } 9654 PetscFunctionReturn(PETSC_SUCCESS); 9655 } 9656 9657 /*@ 9658 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9659 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9660 9661 Not Collective 9662 9663 Input Parameter: 9664 . mat - the matrix 9665 9666 Output Parameters: 9667 + nstash - the size of the stash 9668 . reallocs - the number of additional mallocs incurred. 9669 . bnstash - the size of the block stash 9670 - breallocs - the number of additional mallocs incurred.in the block stash 9671 9672 Level: advanced 9673 9674 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9675 @*/ 9676 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9677 { 9678 PetscFunctionBegin; 9679 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9680 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9681 PetscFunctionReturn(PETSC_SUCCESS); 9682 } 9683 9684 /*@ 9685 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9686 parallel layout, `PetscLayout` for rows and columns 9687 9688 Collective 9689 9690 Input Parameter: 9691 . mat - the matrix 9692 9693 Output Parameters: 9694 + right - (optional) vector that the matrix can be multiplied against 9695 - left - (optional) vector that the matrix vector product can be stored in 9696 9697 Level: advanced 9698 9699 Notes: 9700 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()`. 9701 9702 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9703 9704 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9705 @*/ 9706 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9707 { 9708 PetscFunctionBegin; 9709 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9710 PetscValidType(mat, 1); 9711 if (mat->ops->getvecs) { 9712 PetscUseTypeMethod(mat, getvecs, right, left); 9713 } else { 9714 if (right) { 9715 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9716 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9717 PetscCall(VecSetType(*right, mat->defaultvectype)); 9718 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9719 if (mat->boundtocpu && mat->bindingpropagates) { 9720 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9721 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9722 } 9723 #endif 9724 } 9725 if (left) { 9726 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9727 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9728 PetscCall(VecSetType(*left, mat->defaultvectype)); 9729 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9730 if (mat->boundtocpu && mat->bindingpropagates) { 9731 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9732 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9733 } 9734 #endif 9735 } 9736 } 9737 PetscFunctionReturn(PETSC_SUCCESS); 9738 } 9739 9740 /*@ 9741 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9742 with default values. 9743 9744 Not Collective 9745 9746 Input Parameter: 9747 . info - the `MatFactorInfo` data structure 9748 9749 Level: developer 9750 9751 Notes: 9752 The solvers are generally used through the `KSP` and `PC` objects, for example 9753 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9754 9755 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9756 9757 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9758 @*/ 9759 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9760 { 9761 PetscFunctionBegin; 9762 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9763 PetscFunctionReturn(PETSC_SUCCESS); 9764 } 9765 9766 /*@ 9767 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9768 9769 Collective 9770 9771 Input Parameters: 9772 + mat - the factored matrix 9773 - is - the index set defining the Schur indices (0-based) 9774 9775 Level: advanced 9776 9777 Notes: 9778 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9779 9780 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9781 9782 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9783 9784 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9785 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9786 @*/ 9787 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9788 { 9789 PetscErrorCode (*f)(Mat, IS); 9790 9791 PetscFunctionBegin; 9792 PetscValidType(mat, 1); 9793 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9794 PetscValidType(is, 2); 9795 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9796 PetscCheckSameComm(mat, 1, is, 2); 9797 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9798 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9799 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9800 PetscCall(MatDestroy(&mat->schur)); 9801 PetscCall((*f)(mat, is)); 9802 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9803 PetscFunctionReturn(PETSC_SUCCESS); 9804 } 9805 9806 /*@ 9807 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9808 9809 Logically Collective 9810 9811 Input Parameters: 9812 + F - the factored matrix obtained by calling `MatGetFactor()` 9813 . S - location where to return the Schur complement, can be `NULL` 9814 - status - the status of the Schur complement matrix, can be `NULL` 9815 9816 Level: advanced 9817 9818 Notes: 9819 You must call `MatFactorSetSchurIS()` before calling this routine. 9820 9821 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9822 9823 The routine provides a copy of the Schur matrix stored within the solver data structures. 9824 The caller must destroy the object when it is no longer needed. 9825 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9826 9827 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) 9828 9829 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9830 9831 Developer Note: 9832 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9833 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9834 9835 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9836 @*/ 9837 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9838 { 9839 PetscFunctionBegin; 9840 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9841 if (S) PetscAssertPointer(S, 2); 9842 if (status) PetscAssertPointer(status, 3); 9843 if (S) { 9844 PetscErrorCode (*f)(Mat, Mat *); 9845 9846 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9847 if (f) { 9848 PetscCall((*f)(F, S)); 9849 } else { 9850 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9851 } 9852 } 9853 if (status) *status = F->schur_status; 9854 PetscFunctionReturn(PETSC_SUCCESS); 9855 } 9856 9857 /*@ 9858 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9859 9860 Logically Collective 9861 9862 Input Parameters: 9863 + F - the factored matrix obtained by calling `MatGetFactor()` 9864 . S - location where to return the Schur complement, can be `NULL` 9865 - status - the status of the Schur complement matrix, can be `NULL` 9866 9867 Level: advanced 9868 9869 Notes: 9870 You must call `MatFactorSetSchurIS()` before calling this routine. 9871 9872 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9873 9874 The routine returns a the Schur Complement stored within the data structures of the solver. 9875 9876 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9877 9878 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9879 9880 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9881 9882 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9883 9884 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9885 @*/ 9886 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9887 { 9888 PetscFunctionBegin; 9889 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9890 if (S) { 9891 PetscAssertPointer(S, 2); 9892 *S = F->schur; 9893 } 9894 if (status) { 9895 PetscAssertPointer(status, 3); 9896 *status = F->schur_status; 9897 } 9898 PetscFunctionReturn(PETSC_SUCCESS); 9899 } 9900 9901 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9902 { 9903 Mat S = F->schur; 9904 9905 PetscFunctionBegin; 9906 switch (F->schur_status) { 9907 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9908 case MAT_FACTOR_SCHUR_INVERTED: 9909 if (S) { 9910 S->ops->solve = NULL; 9911 S->ops->matsolve = NULL; 9912 S->ops->solvetranspose = NULL; 9913 S->ops->matsolvetranspose = NULL; 9914 S->ops->solveadd = NULL; 9915 S->ops->solvetransposeadd = NULL; 9916 S->factortype = MAT_FACTOR_NONE; 9917 PetscCall(PetscFree(S->solvertype)); 9918 } 9919 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9920 break; 9921 default: 9922 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9923 } 9924 PetscFunctionReturn(PETSC_SUCCESS); 9925 } 9926 9927 /*@ 9928 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9929 9930 Logically Collective 9931 9932 Input Parameters: 9933 + F - the factored matrix obtained by calling `MatGetFactor()` 9934 . S - location where the Schur complement is stored 9935 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9936 9937 Level: advanced 9938 9939 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9940 @*/ 9941 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9942 { 9943 PetscFunctionBegin; 9944 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9945 if (S) { 9946 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9947 *S = NULL; 9948 } 9949 F->schur_status = status; 9950 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9951 PetscFunctionReturn(PETSC_SUCCESS); 9952 } 9953 9954 /*@ 9955 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9956 9957 Logically Collective 9958 9959 Input Parameters: 9960 + F - the factored matrix obtained by calling `MatGetFactor()` 9961 . rhs - location where the right-hand side of the Schur complement system is stored 9962 - sol - location where the solution of the Schur complement system has to be returned 9963 9964 Level: advanced 9965 9966 Notes: 9967 The sizes of the vectors should match the size of the Schur complement 9968 9969 Must be called after `MatFactorSetSchurIS()` 9970 9971 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9972 @*/ 9973 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9974 { 9975 PetscFunctionBegin; 9976 PetscValidType(F, 1); 9977 PetscValidType(rhs, 2); 9978 PetscValidType(sol, 3); 9979 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9980 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9981 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9982 PetscCheckSameComm(F, 1, rhs, 2); 9983 PetscCheckSameComm(F, 1, sol, 3); 9984 PetscCall(MatFactorFactorizeSchurComplement(F)); 9985 switch (F->schur_status) { 9986 case MAT_FACTOR_SCHUR_FACTORED: 9987 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9988 break; 9989 case MAT_FACTOR_SCHUR_INVERTED: 9990 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9991 break; 9992 default: 9993 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9994 } 9995 PetscFunctionReturn(PETSC_SUCCESS); 9996 } 9997 9998 /*@ 9999 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 10000 10001 Logically Collective 10002 10003 Input Parameters: 10004 + F - the factored matrix obtained by calling `MatGetFactor()` 10005 . rhs - location where the right-hand side of the Schur complement system is stored 10006 - sol - location where the solution of the Schur complement system has to be returned 10007 10008 Level: advanced 10009 10010 Notes: 10011 The sizes of the vectors should match the size of the Schur complement 10012 10013 Must be called after `MatFactorSetSchurIS()` 10014 10015 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10016 @*/ 10017 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10018 { 10019 PetscFunctionBegin; 10020 PetscValidType(F, 1); 10021 PetscValidType(rhs, 2); 10022 PetscValidType(sol, 3); 10023 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10024 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10025 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10026 PetscCheckSameComm(F, 1, rhs, 2); 10027 PetscCheckSameComm(F, 1, sol, 3); 10028 PetscCall(MatFactorFactorizeSchurComplement(F)); 10029 switch (F->schur_status) { 10030 case MAT_FACTOR_SCHUR_FACTORED: 10031 PetscCall(MatSolve(F->schur, rhs, sol)); 10032 break; 10033 case MAT_FACTOR_SCHUR_INVERTED: 10034 PetscCall(MatMult(F->schur, rhs, sol)); 10035 break; 10036 default: 10037 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10038 } 10039 PetscFunctionReturn(PETSC_SUCCESS); 10040 } 10041 10042 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10043 #if PetscDefined(HAVE_CUDA) 10044 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10045 #endif 10046 10047 /* Schur status updated in the interface */ 10048 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10049 { 10050 Mat S = F->schur; 10051 10052 PetscFunctionBegin; 10053 if (S) { 10054 PetscMPIInt size; 10055 PetscBool isdense, isdensecuda; 10056 10057 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10058 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10059 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10060 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10061 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10062 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10063 if (isdense) { 10064 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10065 } else if (isdensecuda) { 10066 #if defined(PETSC_HAVE_CUDA) 10067 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10068 #endif 10069 } 10070 // HIP?????????????? 10071 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10072 } 10073 PetscFunctionReturn(PETSC_SUCCESS); 10074 } 10075 10076 /*@ 10077 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10078 10079 Logically Collective 10080 10081 Input Parameter: 10082 . F - the factored matrix obtained by calling `MatGetFactor()` 10083 10084 Level: advanced 10085 10086 Notes: 10087 Must be called after `MatFactorSetSchurIS()`. 10088 10089 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10090 10091 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10092 @*/ 10093 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10094 { 10095 PetscFunctionBegin; 10096 PetscValidType(F, 1); 10097 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10098 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10099 PetscCall(MatFactorFactorizeSchurComplement(F)); 10100 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10101 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10102 PetscFunctionReturn(PETSC_SUCCESS); 10103 } 10104 10105 /*@ 10106 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10107 10108 Logically Collective 10109 10110 Input Parameter: 10111 . F - the factored matrix obtained by calling `MatGetFactor()` 10112 10113 Level: advanced 10114 10115 Note: 10116 Must be called after `MatFactorSetSchurIS()` 10117 10118 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10119 @*/ 10120 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10121 { 10122 MatFactorInfo info; 10123 10124 PetscFunctionBegin; 10125 PetscValidType(F, 1); 10126 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10127 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10128 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10129 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10130 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10131 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10132 } else { 10133 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10134 } 10135 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10136 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10137 PetscFunctionReturn(PETSC_SUCCESS); 10138 } 10139 10140 /*@ 10141 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10142 10143 Neighbor-wise Collective 10144 10145 Input Parameters: 10146 + A - the matrix 10147 . P - the projection matrix 10148 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10149 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10150 if the result is a dense matrix this is irrelevant 10151 10152 Output Parameter: 10153 . C - the product matrix 10154 10155 Level: intermediate 10156 10157 Notes: 10158 C will be created and must be destroyed by the user with `MatDestroy()`. 10159 10160 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10161 10162 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10163 10164 Developer Note: 10165 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10166 10167 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10168 @*/ 10169 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10170 { 10171 PetscFunctionBegin; 10172 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10173 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10174 10175 if (scall == MAT_INITIAL_MATRIX) { 10176 PetscCall(MatProductCreate(A, P, NULL, C)); 10177 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10178 PetscCall(MatProductSetAlgorithm(*C, "default")); 10179 PetscCall(MatProductSetFill(*C, fill)); 10180 10181 (*C)->product->api_user = PETSC_TRUE; 10182 PetscCall(MatProductSetFromOptions(*C)); 10183 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); 10184 PetscCall(MatProductSymbolic(*C)); 10185 } else { /* scall == MAT_REUSE_MATRIX */ 10186 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10187 } 10188 10189 PetscCall(MatProductNumeric(*C)); 10190 (*C)->symmetric = A->symmetric; 10191 (*C)->spd = A->spd; 10192 PetscFunctionReturn(PETSC_SUCCESS); 10193 } 10194 10195 /*@ 10196 MatRARt - Creates the matrix product $C = R * A * R^T$ 10197 10198 Neighbor-wise Collective 10199 10200 Input Parameters: 10201 + A - the matrix 10202 . R - the projection matrix 10203 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10204 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10205 if the result is a dense matrix this is irrelevant 10206 10207 Output Parameter: 10208 . C - the product matrix 10209 10210 Level: intermediate 10211 10212 Notes: 10213 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10214 10215 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10216 10217 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10218 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10219 parallel `MatRARt()` is implemented via explicit transpose of `R`, which could be very expensive. 10220 We recommend using `MatPtAP()`. 10221 10222 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10223 10224 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10225 @*/ 10226 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10227 { 10228 PetscFunctionBegin; 10229 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10230 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10231 10232 if (scall == MAT_INITIAL_MATRIX) { 10233 PetscCall(MatProductCreate(A, R, NULL, C)); 10234 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10235 PetscCall(MatProductSetAlgorithm(*C, "default")); 10236 PetscCall(MatProductSetFill(*C, fill)); 10237 10238 (*C)->product->api_user = PETSC_TRUE; 10239 PetscCall(MatProductSetFromOptions(*C)); 10240 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); 10241 PetscCall(MatProductSymbolic(*C)); 10242 } else { /* scall == MAT_REUSE_MATRIX */ 10243 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10244 } 10245 10246 PetscCall(MatProductNumeric(*C)); 10247 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10248 PetscFunctionReturn(PETSC_SUCCESS); 10249 } 10250 10251 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10252 { 10253 PetscBool flg = PETSC_TRUE; 10254 10255 PetscFunctionBegin; 10256 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10257 if (scall == MAT_INITIAL_MATRIX) { 10258 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10259 PetscCall(MatProductCreate(A, B, NULL, C)); 10260 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10261 PetscCall(MatProductSetFill(*C, fill)); 10262 } else { /* scall == MAT_REUSE_MATRIX */ 10263 Mat_Product *product = (*C)->product; 10264 10265 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10266 if (flg && product && product->type != ptype) { 10267 PetscCall(MatProductClear(*C)); 10268 product = NULL; 10269 } 10270 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10271 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10272 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10273 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10274 product = (*C)->product; 10275 product->fill = fill; 10276 product->clear = PETSC_TRUE; 10277 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10278 flg = PETSC_FALSE; 10279 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10280 } 10281 } 10282 if (flg) { 10283 (*C)->product->api_user = PETSC_TRUE; 10284 PetscCall(MatProductSetType(*C, ptype)); 10285 PetscCall(MatProductSetFromOptions(*C)); 10286 PetscCall(MatProductSymbolic(*C)); 10287 } 10288 PetscCall(MatProductNumeric(*C)); 10289 PetscFunctionReturn(PETSC_SUCCESS); 10290 } 10291 10292 /*@ 10293 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10294 10295 Neighbor-wise Collective 10296 10297 Input Parameters: 10298 + A - the left matrix 10299 . B - the right matrix 10300 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10301 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10302 if the result is a dense matrix this is irrelevant 10303 10304 Output Parameter: 10305 . C - the product matrix 10306 10307 Notes: 10308 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10309 10310 `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 10311 call to this function with `MAT_INITIAL_MATRIX`. 10312 10313 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10314 10315 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`, 10316 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10317 10318 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10319 10320 Example of Usage: 10321 .vb 10322 MatProductCreate(A,B,NULL,&C); 10323 MatProductSetType(C,MATPRODUCT_AB); 10324 MatProductSymbolic(C); 10325 MatProductNumeric(C); // compute C=A * B 10326 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10327 MatProductNumeric(C); 10328 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10329 MatProductNumeric(C); 10330 .ve 10331 10332 Level: intermediate 10333 10334 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10335 @*/ 10336 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10337 { 10338 PetscFunctionBegin; 10339 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10340 PetscFunctionReturn(PETSC_SUCCESS); 10341 } 10342 10343 /*@ 10344 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10345 10346 Neighbor-wise Collective 10347 10348 Input Parameters: 10349 + A - the left matrix 10350 . B - the right matrix 10351 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10352 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10353 10354 Output Parameter: 10355 . C - the product matrix 10356 10357 Options Database Key: 10358 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10359 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10360 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10361 10362 Level: intermediate 10363 10364 Notes: 10365 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10366 10367 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10368 10369 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10370 actually needed. 10371 10372 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10373 and for pairs of `MATMPIDENSE` matrices. 10374 10375 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10376 10377 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10378 10379 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10380 @*/ 10381 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10382 { 10383 PetscFunctionBegin; 10384 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10385 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10386 PetscFunctionReturn(PETSC_SUCCESS); 10387 } 10388 10389 /*@ 10390 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10391 10392 Neighbor-wise Collective 10393 10394 Input Parameters: 10395 + A - the left matrix 10396 . B - the right matrix 10397 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10398 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10399 10400 Output Parameter: 10401 . C - the product matrix 10402 10403 Level: intermediate 10404 10405 Notes: 10406 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10407 10408 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10409 10410 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10411 10412 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10413 actually needed. 10414 10415 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10416 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10417 10418 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10419 10420 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10421 @*/ 10422 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10423 { 10424 PetscFunctionBegin; 10425 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10426 PetscFunctionReturn(PETSC_SUCCESS); 10427 } 10428 10429 /*@ 10430 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10431 10432 Neighbor-wise Collective 10433 10434 Input Parameters: 10435 + A - the left matrix 10436 . B - the middle matrix 10437 . C - the right matrix 10438 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10439 - fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10440 if the result is a dense matrix this is irrelevant 10441 10442 Output Parameter: 10443 . D - the product matrix 10444 10445 Level: intermediate 10446 10447 Notes: 10448 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10449 10450 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10451 10452 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10453 10454 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10455 actually needed. 10456 10457 If you have many matrices with the same non-zero structure to multiply, you 10458 should use `MAT_REUSE_MATRIX` in all calls but the first 10459 10460 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10461 10462 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10463 @*/ 10464 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10465 { 10466 PetscFunctionBegin; 10467 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10468 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10469 10470 if (scall == MAT_INITIAL_MATRIX) { 10471 PetscCall(MatProductCreate(A, B, C, D)); 10472 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10473 PetscCall(MatProductSetAlgorithm(*D, "default")); 10474 PetscCall(MatProductSetFill(*D, fill)); 10475 10476 (*D)->product->api_user = PETSC_TRUE; 10477 PetscCall(MatProductSetFromOptions(*D)); 10478 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, 10479 ((PetscObject)C)->type_name); 10480 PetscCall(MatProductSymbolic(*D)); 10481 } else { /* user may change input matrices when REUSE */ 10482 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10483 } 10484 PetscCall(MatProductNumeric(*D)); 10485 PetscFunctionReturn(PETSC_SUCCESS); 10486 } 10487 10488 /*@ 10489 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10490 10491 Collective 10492 10493 Input Parameters: 10494 + mat - the matrix 10495 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10496 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10497 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10498 10499 Output Parameter: 10500 . matredundant - redundant matrix 10501 10502 Level: advanced 10503 10504 Notes: 10505 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10506 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10507 10508 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10509 calling it. 10510 10511 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10512 10513 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10514 @*/ 10515 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10516 { 10517 MPI_Comm comm; 10518 PetscMPIInt size; 10519 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10520 Mat_Redundant *redund = NULL; 10521 PetscSubcomm psubcomm = NULL; 10522 MPI_Comm subcomm_in = subcomm; 10523 Mat *matseq; 10524 IS isrow, iscol; 10525 PetscBool newsubcomm = PETSC_FALSE; 10526 10527 PetscFunctionBegin; 10528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10529 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10530 PetscAssertPointer(*matredundant, 5); 10531 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10532 } 10533 10534 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10535 if (size == 1 || nsubcomm == 1) { 10536 if (reuse == MAT_INITIAL_MATRIX) { 10537 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10538 } else { 10539 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"); 10540 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10541 } 10542 PetscFunctionReturn(PETSC_SUCCESS); 10543 } 10544 10545 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10546 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10547 MatCheckPreallocated(mat, 1); 10548 10549 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10550 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10551 /* create psubcomm, then get subcomm */ 10552 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10553 PetscCallMPI(MPI_Comm_size(comm, &size)); 10554 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10555 10556 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10557 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10558 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10559 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10560 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10561 newsubcomm = PETSC_TRUE; 10562 PetscCall(PetscSubcommDestroy(&psubcomm)); 10563 } 10564 10565 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10566 if (reuse == MAT_INITIAL_MATRIX) { 10567 mloc_sub = PETSC_DECIDE; 10568 nloc_sub = PETSC_DECIDE; 10569 if (bs < 1) { 10570 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10571 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10572 } else { 10573 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10574 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10575 } 10576 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10577 rstart = rend - mloc_sub; 10578 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10579 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10580 PetscCall(ISSetIdentity(iscol)); 10581 } else { /* reuse == MAT_REUSE_MATRIX */ 10582 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"); 10583 /* retrieve subcomm */ 10584 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10585 redund = (*matredundant)->redundant; 10586 isrow = redund->isrow; 10587 iscol = redund->iscol; 10588 matseq = redund->matseq; 10589 } 10590 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10591 10592 /* get matredundant over subcomm */ 10593 if (reuse == MAT_INITIAL_MATRIX) { 10594 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10595 10596 /* create a supporting struct and attach it to C for reuse */ 10597 PetscCall(PetscNew(&redund)); 10598 (*matredundant)->redundant = redund; 10599 redund->isrow = isrow; 10600 redund->iscol = iscol; 10601 redund->matseq = matseq; 10602 if (newsubcomm) { 10603 redund->subcomm = subcomm; 10604 } else { 10605 redund->subcomm = MPI_COMM_NULL; 10606 } 10607 } else { 10608 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10609 } 10610 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10611 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10612 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10613 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10614 } 10615 #endif 10616 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10617 PetscFunctionReturn(PETSC_SUCCESS); 10618 } 10619 10620 /*@C 10621 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10622 a given `Mat`. Each submatrix can span multiple procs. 10623 10624 Collective 10625 10626 Input Parameters: 10627 + mat - the matrix 10628 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10629 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10630 10631 Output Parameter: 10632 . subMat - parallel sub-matrices each spanning a given `subcomm` 10633 10634 Level: advanced 10635 10636 Notes: 10637 The submatrix partition across processors is dictated by `subComm` a 10638 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10639 is not restricted to be grouped with consecutive original MPI processes. 10640 10641 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10642 map directly to the layout of the original matrix [wrt the local 10643 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10644 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10645 the `subMat`. However the offDiagMat looses some columns - and this is 10646 reconstructed with `MatSetValues()` 10647 10648 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10649 10650 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10651 @*/ 10652 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10653 { 10654 PetscMPIInt commsize, subCommSize; 10655 10656 PetscFunctionBegin; 10657 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10658 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10659 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10660 10661 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"); 10662 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10663 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10664 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10665 PetscFunctionReturn(PETSC_SUCCESS); 10666 } 10667 10668 /*@ 10669 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10670 10671 Not Collective 10672 10673 Input Parameters: 10674 + mat - matrix to extract local submatrix from 10675 . isrow - local row indices for submatrix 10676 - iscol - local column indices for submatrix 10677 10678 Output Parameter: 10679 . submat - the submatrix 10680 10681 Level: intermediate 10682 10683 Notes: 10684 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10685 10686 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10687 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10688 10689 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10690 `MatSetValuesBlockedLocal()` will also be implemented. 10691 10692 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10693 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10694 10695 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10696 @*/ 10697 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10698 { 10699 PetscFunctionBegin; 10700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10701 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10702 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10703 PetscCheckSameComm(isrow, 2, iscol, 3); 10704 PetscAssertPointer(submat, 4); 10705 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10706 10707 if (mat->ops->getlocalsubmatrix) { 10708 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10709 } else { 10710 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10711 } 10712 PetscFunctionReturn(PETSC_SUCCESS); 10713 } 10714 10715 /*@ 10716 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10717 10718 Not Collective 10719 10720 Input Parameters: 10721 + mat - matrix to extract local submatrix from 10722 . isrow - local row indices for submatrix 10723 . iscol - local column indices for submatrix 10724 - submat - the submatrix 10725 10726 Level: intermediate 10727 10728 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10729 @*/ 10730 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10731 { 10732 PetscFunctionBegin; 10733 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10734 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10735 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10736 PetscCheckSameComm(isrow, 2, iscol, 3); 10737 PetscAssertPointer(submat, 4); 10738 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10739 10740 if (mat->ops->restorelocalsubmatrix) { 10741 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10742 } else { 10743 PetscCall(MatDestroy(submat)); 10744 } 10745 *submat = NULL; 10746 PetscFunctionReturn(PETSC_SUCCESS); 10747 } 10748 10749 /*@ 10750 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10751 10752 Collective 10753 10754 Input Parameter: 10755 . mat - the matrix 10756 10757 Output Parameter: 10758 . is - if any rows have zero diagonals this contains the list of them 10759 10760 Level: developer 10761 10762 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10763 @*/ 10764 PetscErrorCode MatFindZeroDiagonals(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 if (!mat->ops->findzerodiagonals) { 10773 Vec diag; 10774 const PetscScalar *a; 10775 PetscInt *rows; 10776 PetscInt rStart, rEnd, r, nrow = 0; 10777 10778 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10779 PetscCall(MatGetDiagonal(mat, diag)); 10780 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10781 PetscCall(VecGetArrayRead(diag, &a)); 10782 for (r = 0; r < rEnd - rStart; ++r) 10783 if (a[r] == 0.0) ++nrow; 10784 PetscCall(PetscMalloc1(nrow, &rows)); 10785 nrow = 0; 10786 for (r = 0; r < rEnd - rStart; ++r) 10787 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10788 PetscCall(VecRestoreArrayRead(diag, &a)); 10789 PetscCall(VecDestroy(&diag)); 10790 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10791 } else { 10792 PetscUseTypeMethod(mat, findzerodiagonals, is); 10793 } 10794 PetscFunctionReturn(PETSC_SUCCESS); 10795 } 10796 10797 /*@ 10798 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10799 10800 Collective 10801 10802 Input Parameter: 10803 . mat - the matrix 10804 10805 Output Parameter: 10806 . is - contains the list of rows with off block diagonal entries 10807 10808 Level: developer 10809 10810 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10811 @*/ 10812 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10813 { 10814 PetscFunctionBegin; 10815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10816 PetscValidType(mat, 1); 10817 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10818 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10819 10820 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10821 PetscFunctionReturn(PETSC_SUCCESS); 10822 } 10823 10824 /*@C 10825 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10826 10827 Collective; No Fortran Support 10828 10829 Input Parameter: 10830 . mat - the matrix 10831 10832 Output Parameter: 10833 . values - the block inverses in column major order (FORTRAN-like) 10834 10835 Level: advanced 10836 10837 Notes: 10838 The size of the blocks is determined by the block size of the matrix. 10839 10840 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10841 10842 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10843 10844 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10845 @*/ 10846 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10847 { 10848 PetscFunctionBegin; 10849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10850 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10851 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10852 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10853 PetscFunctionReturn(PETSC_SUCCESS); 10854 } 10855 10856 /*@ 10857 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10858 10859 Collective; No Fortran Support 10860 10861 Input Parameters: 10862 + mat - the matrix 10863 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10864 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10865 10866 Output Parameter: 10867 . values - the block inverses in column major order (FORTRAN-like) 10868 10869 Level: advanced 10870 10871 Notes: 10872 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10873 10874 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10875 10876 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10877 @*/ 10878 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10879 { 10880 PetscFunctionBegin; 10881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10882 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10883 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10884 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10885 PetscFunctionReturn(PETSC_SUCCESS); 10886 } 10887 10888 /*@ 10889 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10890 10891 Collective 10892 10893 Input Parameters: 10894 + A - the matrix 10895 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10896 10897 Level: advanced 10898 10899 Note: 10900 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10901 10902 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10903 @*/ 10904 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10905 { 10906 const PetscScalar *vals; 10907 PetscInt *dnnz; 10908 PetscInt m, rstart, rend, bs, i, j; 10909 10910 PetscFunctionBegin; 10911 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10912 PetscCall(MatGetBlockSize(A, &bs)); 10913 PetscCall(MatGetLocalSize(A, &m, NULL)); 10914 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10915 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10916 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10917 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10918 PetscCall(PetscFree(dnnz)); 10919 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10920 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10921 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10922 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10923 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10924 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10925 PetscFunctionReturn(PETSC_SUCCESS); 10926 } 10927 10928 /*@ 10929 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10930 via `MatTransposeColoringCreate()`. 10931 10932 Collective 10933 10934 Input Parameter: 10935 . c - coloring context 10936 10937 Level: intermediate 10938 10939 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10940 @*/ 10941 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10942 { 10943 MatTransposeColoring matcolor = *c; 10944 10945 PetscFunctionBegin; 10946 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10947 if (--((PetscObject)matcolor)->refct > 0) { 10948 matcolor = NULL; 10949 PetscFunctionReturn(PETSC_SUCCESS); 10950 } 10951 10952 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10953 PetscCall(PetscFree(matcolor->rows)); 10954 PetscCall(PetscFree(matcolor->den2sp)); 10955 PetscCall(PetscFree(matcolor->colorforcol)); 10956 PetscCall(PetscFree(matcolor->columns)); 10957 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10958 PetscCall(PetscHeaderDestroy(c)); 10959 PetscFunctionReturn(PETSC_SUCCESS); 10960 } 10961 10962 /*@ 10963 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10964 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10965 `MatTransposeColoring` to sparse `B`. 10966 10967 Collective 10968 10969 Input Parameters: 10970 + coloring - coloring context created with `MatTransposeColoringCreate()` 10971 - B - sparse matrix 10972 10973 Output Parameter: 10974 . Btdense - dense matrix $B^T$ 10975 10976 Level: developer 10977 10978 Note: 10979 These are used internally for some implementations of `MatRARt()` 10980 10981 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10982 @*/ 10983 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10984 { 10985 PetscFunctionBegin; 10986 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10987 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10988 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10989 10990 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10991 PetscFunctionReturn(PETSC_SUCCESS); 10992 } 10993 10994 /*@ 10995 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10996 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10997 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10998 $C_{sp}$ from $C_{den}$. 10999 11000 Collective 11001 11002 Input Parameters: 11003 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 11004 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 11005 11006 Output Parameter: 11007 . Csp - sparse matrix 11008 11009 Level: developer 11010 11011 Note: 11012 These are used internally for some implementations of `MatRARt()` 11013 11014 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11015 @*/ 11016 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11017 { 11018 PetscFunctionBegin; 11019 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11020 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11021 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11022 11023 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11024 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11025 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11026 PetscFunctionReturn(PETSC_SUCCESS); 11027 } 11028 11029 /*@ 11030 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11031 11032 Collective 11033 11034 Input Parameters: 11035 + mat - the matrix product C 11036 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11037 11038 Output Parameter: 11039 . color - the new coloring context 11040 11041 Level: intermediate 11042 11043 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11044 `MatTransColoringApplyDenToSp()` 11045 @*/ 11046 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11047 { 11048 MatTransposeColoring c; 11049 MPI_Comm comm; 11050 11051 PetscFunctionBegin; 11052 PetscAssertPointer(color, 3); 11053 11054 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11055 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11056 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11057 c->ctype = iscoloring->ctype; 11058 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11059 *color = c; 11060 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11061 PetscFunctionReturn(PETSC_SUCCESS); 11062 } 11063 11064 /*@ 11065 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11066 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11067 11068 Not Collective 11069 11070 Input Parameter: 11071 . mat - the matrix 11072 11073 Output Parameter: 11074 . state - the current state 11075 11076 Level: intermediate 11077 11078 Notes: 11079 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11080 different matrices 11081 11082 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11083 11084 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11085 11086 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11087 @*/ 11088 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11089 { 11090 PetscFunctionBegin; 11091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11092 *state = mat->nonzerostate; 11093 PetscFunctionReturn(PETSC_SUCCESS); 11094 } 11095 11096 /*@ 11097 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11098 matrices from each processor 11099 11100 Collective 11101 11102 Input Parameters: 11103 + comm - the communicators the parallel matrix will live on 11104 . seqmat - the input sequential matrices 11105 . n - number of local columns (or `PETSC_DECIDE`) 11106 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11107 11108 Output Parameter: 11109 . mpimat - the parallel matrix generated 11110 11111 Level: developer 11112 11113 Note: 11114 The number of columns of the matrix in EACH processor MUST be the same. 11115 11116 .seealso: [](ch_matrices), `Mat` 11117 @*/ 11118 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11119 { 11120 PetscMPIInt size; 11121 11122 PetscFunctionBegin; 11123 PetscCallMPI(MPI_Comm_size(comm, &size)); 11124 if (size == 1) { 11125 if (reuse == MAT_INITIAL_MATRIX) { 11126 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11127 } else { 11128 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11129 } 11130 PetscFunctionReturn(PETSC_SUCCESS); 11131 } 11132 11133 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"); 11134 11135 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11136 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11137 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11138 PetscFunctionReturn(PETSC_SUCCESS); 11139 } 11140 11141 /*@ 11142 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11143 11144 Collective 11145 11146 Input Parameters: 11147 + A - the matrix to create subdomains from 11148 - N - requested number of subdomains 11149 11150 Output Parameters: 11151 + n - number of subdomains resulting on this MPI process 11152 - iss - `IS` list with indices of subdomains on this MPI process 11153 11154 Level: advanced 11155 11156 Note: 11157 The number of subdomains must be smaller than the communicator size 11158 11159 .seealso: [](ch_matrices), `Mat`, `IS` 11160 @*/ 11161 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11162 { 11163 MPI_Comm comm, subcomm; 11164 PetscMPIInt size, rank, color; 11165 PetscInt rstart, rend, k; 11166 11167 PetscFunctionBegin; 11168 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11169 PetscCallMPI(MPI_Comm_size(comm, &size)); 11170 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11171 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); 11172 *n = 1; 11173 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11174 color = rank / k; 11175 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11176 PetscCall(PetscMalloc1(1, iss)); 11177 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11178 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11179 PetscCallMPI(MPI_Comm_free(&subcomm)); 11180 PetscFunctionReturn(PETSC_SUCCESS); 11181 } 11182 11183 /*@ 11184 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11185 11186 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11187 If they are not the same, uses `MatMatMatMult()`. 11188 11189 Once the coarse grid problem is constructed, correct for interpolation operators 11190 that are not of full rank, which can legitimately happen in the case of non-nested 11191 geometric multigrid. 11192 11193 Input Parameters: 11194 + restrct - restriction operator 11195 . dA - fine grid matrix 11196 . interpolate - interpolation operator 11197 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11198 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11199 11200 Output Parameter: 11201 . A - the Galerkin coarse matrix 11202 11203 Options Database Key: 11204 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11205 11206 Level: developer 11207 11208 Note: 11209 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11210 11211 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11212 @*/ 11213 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11214 { 11215 IS zerorows; 11216 Vec diag; 11217 11218 PetscFunctionBegin; 11219 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11220 /* Construct the coarse grid matrix */ 11221 if (interpolate == restrct) { 11222 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11223 } else { 11224 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11225 } 11226 11227 /* If the interpolation matrix is not of full rank, A will have zero rows. 11228 This can legitimately happen in the case of non-nested geometric multigrid. 11229 In that event, we set the rows of the matrix to the rows of the identity, 11230 ignoring the equations (as the RHS will also be zero). */ 11231 11232 PetscCall(MatFindZeroRows(*A, &zerorows)); 11233 11234 if (zerorows != NULL) { /* if there are any zero rows */ 11235 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11236 PetscCall(MatGetDiagonal(*A, diag)); 11237 PetscCall(VecISSet(diag, zerorows, 1.0)); 11238 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11239 PetscCall(VecDestroy(&diag)); 11240 PetscCall(ISDestroy(&zerorows)); 11241 } 11242 PetscFunctionReturn(PETSC_SUCCESS); 11243 } 11244 11245 /*@C 11246 MatSetOperation - Allows user to set a matrix operation for any matrix type 11247 11248 Logically Collective 11249 11250 Input Parameters: 11251 + mat - the matrix 11252 . op - the name of the operation 11253 - f - the function that provides the operation 11254 11255 Level: developer 11256 11257 Example Usage: 11258 .vb 11259 extern PetscErrorCode usermult(Mat, Vec, Vec); 11260 11261 PetscCall(MatCreateXXX(comm, ..., &A)); 11262 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)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 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11272 sequence as the usual matrix interface routines, since they 11273 are intended to be accessed via the usual matrix interface 11274 routines, e.g., 11275 .vb 11276 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11277 .ve 11278 11279 In particular each function MUST return `PETSC_SUCCESS` on success and 11280 nonzero on failure. 11281 11282 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11283 11284 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11285 @*/ 11286 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11287 { 11288 PetscFunctionBegin; 11289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11290 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11291 (((void (**)(void))mat->ops)[op]) = f; 11292 PetscFunctionReturn(PETSC_SUCCESS); 11293 } 11294 11295 /*@C 11296 MatGetOperation - Gets a matrix operation for any matrix type. 11297 11298 Not Collective 11299 11300 Input Parameters: 11301 + mat - the matrix 11302 - op - the name of the operation 11303 11304 Output Parameter: 11305 . f - the function that provides the operation 11306 11307 Level: developer 11308 11309 Example Usage: 11310 .vb 11311 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11312 11313 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11314 .ve 11315 11316 Notes: 11317 See the file include/petscmat.h for a complete list of matrix 11318 operations, which all have the form MATOP_<OPERATION>, where 11319 <OPERATION> is the name (in all capital letters) of the 11320 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11321 11322 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11323 11324 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11325 @*/ 11326 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11327 { 11328 PetscFunctionBegin; 11329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11330 *f = (((void (**)(void))mat->ops)[op]); 11331 PetscFunctionReturn(PETSC_SUCCESS); 11332 } 11333 11334 /*@ 11335 MatHasOperation - Determines whether the given matrix supports the particular operation. 11336 11337 Not Collective 11338 11339 Input Parameters: 11340 + mat - the matrix 11341 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11342 11343 Output Parameter: 11344 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11345 11346 Level: advanced 11347 11348 Note: 11349 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11350 11351 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11352 @*/ 11353 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11354 { 11355 PetscFunctionBegin; 11356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11357 PetscAssertPointer(has, 3); 11358 if (mat->ops->hasoperation) { 11359 PetscUseTypeMethod(mat, hasoperation, op, has); 11360 } else { 11361 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11362 else { 11363 *has = PETSC_FALSE; 11364 if (op == MATOP_CREATE_SUBMATRIX) { 11365 PetscMPIInt size; 11366 11367 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11368 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11369 } 11370 } 11371 } 11372 PetscFunctionReturn(PETSC_SUCCESS); 11373 } 11374 11375 /*@ 11376 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11377 11378 Collective 11379 11380 Input Parameter: 11381 . mat - the matrix 11382 11383 Output Parameter: 11384 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11385 11386 Level: beginner 11387 11388 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11389 @*/ 11390 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11391 { 11392 PetscFunctionBegin; 11393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11394 PetscValidType(mat, 1); 11395 PetscAssertPointer(cong, 2); 11396 if (!mat->rmap || !mat->cmap) { 11397 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11398 PetscFunctionReturn(PETSC_SUCCESS); 11399 } 11400 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11401 PetscCall(PetscLayoutSetUp(mat->rmap)); 11402 PetscCall(PetscLayoutSetUp(mat->cmap)); 11403 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11404 if (*cong) mat->congruentlayouts = 1; 11405 else mat->congruentlayouts = 0; 11406 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11407 PetscFunctionReturn(PETSC_SUCCESS); 11408 } 11409 11410 PetscErrorCode MatSetInf(Mat A) 11411 { 11412 PetscFunctionBegin; 11413 PetscUseTypeMethod(A, setinf); 11414 PetscFunctionReturn(PETSC_SUCCESS); 11415 } 11416 11417 /*@ 11418 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 11419 and possibly removes small values from the graph structure. 11420 11421 Collective 11422 11423 Input Parameters: 11424 + A - the matrix 11425 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11426 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11427 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11428 . num_idx - size of 'index' array 11429 - index - array of block indices to use for graph strength of connection weight 11430 11431 Output Parameter: 11432 . graph - the resulting graph 11433 11434 Level: advanced 11435 11436 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11437 @*/ 11438 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11439 { 11440 PetscFunctionBegin; 11441 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11442 PetscValidType(A, 1); 11443 PetscValidLogicalCollectiveBool(A, scale, 3); 11444 PetscAssertPointer(graph, 7); 11445 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11446 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11447 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11448 PetscFunctionReturn(PETSC_SUCCESS); 11449 } 11450 11451 /*@ 11452 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11453 meaning the same memory is used for the matrix, and no new memory is allocated. 11454 11455 Collective 11456 11457 Input Parameters: 11458 + A - the matrix 11459 - 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 11460 11461 Level: intermediate 11462 11463 Developer Note: 11464 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11465 of the arrays in the data structure are unneeded. 11466 11467 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11468 @*/ 11469 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11470 { 11471 PetscFunctionBegin; 11472 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11473 PetscUseTypeMethod(A, eliminatezeros, keep); 11474 PetscFunctionReturn(PETSC_SUCCESS); 11475 } 11476