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 PetscCallMPI(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 preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: beginner 911 912 Notes: 913 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 914 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 915 makes all of the preallocation space available 916 917 Current values in the matrix are lost in this call. 918 919 Currently only supported for `MATAIJ` matrices. 920 921 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 922 @*/ 923 PetscErrorCode MatResetPreallocation(Mat A) 924 { 925 PetscFunctionBegin; 926 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 927 PetscValidType(A, 1); 928 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()"); 929 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 930 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 931 PetscFunctionReturn(PETSC_SUCCESS); 932 } 933 934 /*@ 935 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 936 937 Collective 938 939 Input Parameter: 940 . A - the matrix 941 942 Level: advanced 943 944 Notes: 945 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 946 setting values in the matrix. 947 948 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 949 950 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 951 @*/ 952 PetscErrorCode MatSetUp(Mat A) 953 { 954 PetscFunctionBegin; 955 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 956 if (!((PetscObject)A)->type_name) { 957 PetscMPIInt size; 958 959 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 960 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 961 } 962 if (!A->preallocated) PetscTryTypeMethod(A, setup); 963 PetscCall(PetscLayoutSetUp(A->rmap)); 964 PetscCall(PetscLayoutSetUp(A->cmap)); 965 A->preallocated = PETSC_TRUE; 966 PetscFunctionReturn(PETSC_SUCCESS); 967 } 968 969 #if defined(PETSC_HAVE_SAWS) 970 #include <petscviewersaws.h> 971 #endif 972 973 /* 974 If threadsafety is on extraneous matrices may be printed 975 976 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 977 */ 978 #if !defined(PETSC_HAVE_THREADSAFETY) 979 static PetscInt insidematview = 0; 980 #endif 981 982 /*@ 983 MatViewFromOptions - View properties of the matrix based on options set in the options database 984 985 Collective 986 987 Input Parameters: 988 + A - the matrix 989 . obj - optional additional object that provides the options prefix to use 990 - name - command line option 991 992 Options Database Key: 993 . -mat_view [viewertype]:... - the viewer and its options 994 995 Level: intermediate 996 997 Note: 998 .vb 999 If no value is provided ascii:stdout is used 1000 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1001 for example ascii::ascii_info prints just the information about the object not all details 1002 unless :append is given filename opens in write mode, overwriting what was already there 1003 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1004 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1005 socket[:port] defaults to the standard output port 1006 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1007 .ve 1008 1009 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1010 @*/ 1011 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1012 { 1013 PetscFunctionBegin; 1014 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1015 #if !defined(PETSC_HAVE_THREADSAFETY) 1016 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1017 #endif 1018 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1019 PetscFunctionReturn(PETSC_SUCCESS); 1020 } 1021 1022 /*@ 1023 MatView - display information about a matrix in a variety ways 1024 1025 Collective on viewer 1026 1027 Input Parameters: 1028 + mat - the matrix 1029 - viewer - visualization context 1030 1031 Options Database Keys: 1032 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1033 . -mat_view ::ascii_info_detail - Prints more detailed info 1034 . -mat_view - Prints matrix in ASCII format 1035 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1036 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1037 . -display <name> - Sets display name (default is host) 1038 . -draw_pause <sec> - Sets number of seconds to pause after display 1039 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1040 . -viewer_socket_machine <machine> - - 1041 . -viewer_socket_port <port> - - 1042 . -mat_view binary - save matrix to file in binary format 1043 - -viewer_binary_filename <name> - - 1044 1045 Level: beginner 1046 1047 Notes: 1048 The available visualization contexts include 1049 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1050 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1051 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1052 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1053 1054 The user can open alternative visualization contexts with 1055 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1056 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1057 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1058 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1059 1060 The user can call `PetscViewerPushFormat()` to specify the output 1061 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1062 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1063 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1064 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1065 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1066 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1067 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1068 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1069 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1070 1071 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1072 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1073 1074 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1075 1076 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1077 viewer is used. 1078 1079 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1080 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1081 1082 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1083 and then use the following mouse functions. 1084 .vb 1085 left mouse: zoom in 1086 middle mouse: zoom out 1087 right mouse: continue with the simulation 1088 .ve 1089 1090 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1091 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1092 @*/ 1093 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1094 { 1095 PetscInt rows, cols, rbs, cbs; 1096 PetscBool isascii, isstring, issaws; 1097 PetscViewerFormat format; 1098 PetscMPIInt size; 1099 1100 PetscFunctionBegin; 1101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1102 PetscValidType(mat, 1); 1103 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1104 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1105 1106 PetscCall(PetscViewerGetFormat(viewer, &format)); 1107 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1108 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1109 1110 #if !defined(PETSC_HAVE_THREADSAFETY) 1111 insidematview++; 1112 #endif 1113 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1114 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1115 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1116 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"); 1117 1118 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1119 if (isascii) { 1120 if (!mat->preallocated) { 1121 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1122 #if !defined(PETSC_HAVE_THREADSAFETY) 1123 insidematview--; 1124 #endif 1125 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1126 PetscFunctionReturn(PETSC_SUCCESS); 1127 } 1128 if (!mat->assembled) { 1129 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1130 #if !defined(PETSC_HAVE_THREADSAFETY) 1131 insidematview--; 1132 #endif 1133 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1134 PetscFunctionReturn(PETSC_SUCCESS); 1135 } 1136 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1137 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1138 MatNullSpace nullsp, transnullsp; 1139 1140 PetscCall(PetscViewerASCIIPushTab(viewer)); 1141 PetscCall(MatGetSize(mat, &rows, &cols)); 1142 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1143 if (rbs != 1 || cbs != 1) { 1144 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" : "")); 1145 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1146 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1147 if (mat->factortype) { 1148 MatSolverType solver; 1149 PetscCall(MatFactorGetSolverType(mat, &solver)); 1150 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1151 } 1152 if (mat->ops->getinfo) { 1153 MatInfo info; 1154 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1155 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1156 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1157 } 1158 PetscCall(MatGetNullSpace(mat, &nullsp)); 1159 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1160 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1161 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1162 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1163 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1164 PetscCall(PetscViewerASCIIPushTab(viewer)); 1165 PetscCall(MatProductView(mat, viewer)); 1166 PetscCall(PetscViewerASCIIPopTab(viewer)); 1167 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1168 IS tmp; 1169 1170 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1171 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1172 PetscCall(PetscViewerASCIIPushTab(viewer)); 1173 PetscCall(ISView(tmp, viewer)); 1174 PetscCall(PetscViewerASCIIPopTab(viewer)); 1175 PetscCall(ISDestroy(&tmp)); 1176 } 1177 } 1178 } else if (issaws) { 1179 #if defined(PETSC_HAVE_SAWS) 1180 PetscMPIInt rank; 1181 1182 PetscCall(PetscObjectName((PetscObject)mat)); 1183 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1184 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1185 #endif 1186 } else if (isstring) { 1187 const char *type; 1188 PetscCall(MatGetType(mat, &type)); 1189 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1190 PetscTryTypeMethod(mat, view, viewer); 1191 } 1192 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1193 PetscCall(PetscViewerASCIIPushTab(viewer)); 1194 PetscUseTypeMethod(mat, viewnative, viewer); 1195 PetscCall(PetscViewerASCIIPopTab(viewer)); 1196 } else if (mat->ops->view) { 1197 PetscCall(PetscViewerASCIIPushTab(viewer)); 1198 PetscUseTypeMethod(mat, view, viewer); 1199 PetscCall(PetscViewerASCIIPopTab(viewer)); 1200 } 1201 if (isascii) { 1202 PetscCall(PetscViewerGetFormat(viewer, &format)); 1203 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1204 } 1205 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1206 #if !defined(PETSC_HAVE_THREADSAFETY) 1207 insidematview--; 1208 #endif 1209 PetscFunctionReturn(PETSC_SUCCESS); 1210 } 1211 1212 #if defined(PETSC_USE_DEBUG) 1213 #include <../src/sys/totalview/tv_data_display.h> 1214 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1215 { 1216 TV_add_row("Local rows", "int", &mat->rmap->n); 1217 TV_add_row("Local columns", "int", &mat->cmap->n); 1218 TV_add_row("Global rows", "int", &mat->rmap->N); 1219 TV_add_row("Global columns", "int", &mat->cmap->N); 1220 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1221 return TV_format_OK; 1222 } 1223 #endif 1224 1225 /*@ 1226 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1227 with `MatView()`. The matrix format is determined from the options database. 1228 Generates a parallel MPI matrix if the communicator has more than one 1229 processor. The default matrix type is `MATAIJ`. 1230 1231 Collective 1232 1233 Input Parameters: 1234 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1235 or some related function before a call to `MatLoad()` 1236 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1237 1238 Options Database Key: 1239 . -matload_block_size <bs> - set block size 1240 1241 Level: beginner 1242 1243 Notes: 1244 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1245 `Mat` before calling this routine if you wish to set it from the options database. 1246 1247 `MatLoad()` automatically loads into the options database any options 1248 given in the file filename.info where filename is the name of the file 1249 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1250 file will be ignored if you use the -viewer_binary_skip_info option. 1251 1252 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1253 sets the default matrix type AIJ and sets the local and global sizes. 1254 If type and/or size is already set, then the same are used. 1255 1256 In parallel, each processor can load a subset of rows (or the 1257 entire matrix). This routine is especially useful when a large 1258 matrix is stored on disk and only part of it is desired on each 1259 processor. For example, a parallel solver may access only some of 1260 the rows from each processor. The algorithm used here reads 1261 relatively small blocks of data rather than reading the entire 1262 matrix and then subsetting it. 1263 1264 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1265 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1266 or the sequence like 1267 .vb 1268 `PetscViewer` v; 1269 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1270 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1271 `PetscViewerSetFromOptions`(v); 1272 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1273 `PetscViewerFileSetName`(v,"datafile"); 1274 .ve 1275 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1276 $ -viewer_type {binary, hdf5} 1277 1278 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1279 and src/mat/tutorials/ex10.c with the second approach. 1280 1281 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1282 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1283 Multiple objects, both matrices and vectors, can be stored within the same file. 1284 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1285 1286 Most users should not need to know the details of the binary storage 1287 format, since `MatLoad()` and `MatView()` completely hide these details. 1288 But for anyone who is interested, the standard binary matrix storage 1289 format is 1290 1291 .vb 1292 PetscInt MAT_FILE_CLASSID 1293 PetscInt number of rows 1294 PetscInt number of columns 1295 PetscInt total number of nonzeros 1296 PetscInt *number nonzeros in each row 1297 PetscInt *column indices of all nonzeros (starting index is zero) 1298 PetscScalar *values of all nonzeros 1299 .ve 1300 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1301 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 1302 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1303 1304 PETSc automatically does the byte swapping for 1305 machines that store the bytes reversed. Thus if you write your own binary 1306 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1307 and `PetscBinaryWrite()` to see how this may be done. 1308 1309 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1310 Each processor's chunk is loaded independently by its owning MPI process. 1311 Multiple objects, both matrices and vectors, can be stored within the same file. 1312 They are looked up by their PetscObject name. 1313 1314 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1315 by default the same structure and naming of the AIJ arrays and column count 1316 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1317 $ save example.mat A b -v7.3 1318 can be directly read by this routine (see Reference 1 for details). 1319 1320 Depending on your MATLAB version, this format might be a default, 1321 otherwise you can set it as default in Preferences. 1322 1323 Unless -nocompression flag is used to save the file in MATLAB, 1324 PETSc must be configured with ZLIB package. 1325 1326 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1327 1328 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1329 1330 Corresponding `MatView()` is not yet implemented. 1331 1332 The loaded matrix is actually a transpose of the original one in MATLAB, 1333 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1334 With this format, matrix is automatically transposed by PETSc, 1335 unless the matrix is marked as SPD or symmetric 1336 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1337 1338 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1339 1340 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1341 @*/ 1342 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1343 { 1344 PetscBool flg; 1345 1346 PetscFunctionBegin; 1347 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1348 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1349 1350 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1351 1352 flg = PETSC_FALSE; 1353 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1354 if (flg) { 1355 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1356 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1357 } 1358 flg = PETSC_FALSE; 1359 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1360 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1361 1362 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1363 PetscUseTypeMethod(mat, load, viewer); 1364 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1365 PetscFunctionReturn(PETSC_SUCCESS); 1366 } 1367 1368 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1369 { 1370 Mat_Redundant *redund = *redundant; 1371 1372 PetscFunctionBegin; 1373 if (redund) { 1374 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1375 PetscCall(ISDestroy(&redund->isrow)); 1376 PetscCall(ISDestroy(&redund->iscol)); 1377 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1378 } else { 1379 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1380 PetscCall(PetscFree(redund->sbuf_j)); 1381 PetscCall(PetscFree(redund->sbuf_a)); 1382 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1383 PetscCall(PetscFree(redund->rbuf_j[i])); 1384 PetscCall(PetscFree(redund->rbuf_a[i])); 1385 } 1386 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1387 } 1388 1389 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1390 PetscCall(PetscFree(redund)); 1391 } 1392 PetscFunctionReturn(PETSC_SUCCESS); 1393 } 1394 1395 /*@ 1396 MatDestroy - Frees space taken by a matrix. 1397 1398 Collective 1399 1400 Input Parameter: 1401 . A - the matrix 1402 1403 Level: beginner 1404 1405 Developer Note: 1406 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1407 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1408 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1409 if changes are needed here. 1410 1411 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1412 @*/ 1413 PetscErrorCode MatDestroy(Mat *A) 1414 { 1415 PetscFunctionBegin; 1416 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1417 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1418 if (--((PetscObject)*A)->refct > 0) { 1419 *A = NULL; 1420 PetscFunctionReturn(PETSC_SUCCESS); 1421 } 1422 1423 /* if memory was published with SAWs then destroy it */ 1424 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1425 PetscTryTypeMethod(*A, destroy); 1426 1427 PetscCall(PetscFree((*A)->factorprefix)); 1428 PetscCall(PetscFree((*A)->defaultvectype)); 1429 PetscCall(PetscFree((*A)->defaultrandtype)); 1430 PetscCall(PetscFree((*A)->bsizes)); 1431 PetscCall(PetscFree((*A)->solvertype)); 1432 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1433 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1434 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1435 PetscCall(MatProductClear(*A)); 1436 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1437 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1438 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1439 PetscCall(MatDestroy(&(*A)->schur)); 1440 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1441 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1442 PetscCall(PetscHeaderDestroy(A)); 1443 PetscFunctionReturn(PETSC_SUCCESS); 1444 } 1445 1446 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1447 /*@ 1448 MatSetValues - Inserts or adds a block of values into a matrix. 1449 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1450 MUST be called after all calls to `MatSetValues()` have been completed. 1451 1452 Not Collective 1453 1454 Input Parameters: 1455 + mat - the matrix 1456 . v - a logically two-dimensional array of values 1457 . m - the number of rows 1458 . idxm - the global indices of the rows 1459 . n - the number of columns 1460 . idxn - the global indices of the columns 1461 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1462 1463 Level: beginner 1464 1465 Notes: 1466 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1467 1468 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1469 options cannot be mixed without intervening calls to the assembly 1470 routines. 1471 1472 `MatSetValues()` uses 0-based row and column numbers in Fortran 1473 as well as in C. 1474 1475 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1476 simply ignored. This allows easily inserting element stiffness matrices 1477 with homogeneous Dirichlet boundary conditions that you don't want represented 1478 in the matrix. 1479 1480 Efficiency Alert: 1481 The routine `MatSetValuesBlocked()` may offer much better efficiency 1482 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1483 1484 Fortran Notes: 1485 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1486 .vb 1487 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1488 .ve 1489 1490 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1491 1492 Developer Note: 1493 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1494 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1495 1496 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1497 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1498 @*/ 1499 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1500 { 1501 PetscFunctionBeginHot; 1502 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1503 PetscValidType(mat, 1); 1504 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1505 PetscAssertPointer(idxm, 3); 1506 PetscAssertPointer(idxn, 5); 1507 MatCheckPreallocated(mat, 1); 1508 1509 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1510 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1511 1512 if (PetscDefined(USE_DEBUG)) { 1513 PetscInt i, j; 1514 1515 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1516 if (v) { 1517 for (i = 0; i < m; i++) { 1518 for (j = 0; j < n; j++) { 1519 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1520 #if defined(PETSC_USE_COMPLEX) 1521 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]); 1522 #else 1523 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]); 1524 #endif 1525 } 1526 } 1527 } 1528 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); 1529 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); 1530 } 1531 1532 if (mat->assembled) { 1533 mat->was_assembled = PETSC_TRUE; 1534 mat->assembled = PETSC_FALSE; 1535 } 1536 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1537 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1538 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1539 PetscFunctionReturn(PETSC_SUCCESS); 1540 } 1541 1542 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1543 /*@ 1544 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1545 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1546 MUST be called after all calls to `MatSetValues()` have been completed. 1547 1548 Not Collective 1549 1550 Input Parameters: 1551 + mat - the matrix 1552 . v - a logically two-dimensional array of values 1553 . ism - the rows to provide 1554 . isn - the columns to provide 1555 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1556 1557 Level: beginner 1558 1559 Notes: 1560 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1561 1562 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1563 options cannot be mixed without intervening calls to the assembly 1564 routines. 1565 1566 `MatSetValues()` uses 0-based row and column numbers in Fortran 1567 as well as in C. 1568 1569 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1570 simply ignored. This allows easily inserting element stiffness matrices 1571 with homogeneous Dirichlet boundary conditions that you don't want represented 1572 in the matrix. 1573 1574 Efficiency Alert: 1575 The routine `MatSetValuesBlocked()` may offer much better efficiency 1576 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1577 1578 This is currently not optimized for any particular `ISType` 1579 1580 Developer Note: 1581 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1582 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1583 1584 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1585 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1586 @*/ 1587 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1588 { 1589 PetscInt m, n; 1590 const PetscInt *rows, *cols; 1591 1592 PetscFunctionBeginHot; 1593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1594 PetscCall(ISGetIndices(ism, &rows)); 1595 PetscCall(ISGetIndices(isn, &cols)); 1596 PetscCall(ISGetLocalSize(ism, &m)); 1597 PetscCall(ISGetLocalSize(isn, &n)); 1598 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1599 PetscCall(ISRestoreIndices(ism, &rows)); 1600 PetscCall(ISRestoreIndices(isn, &cols)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 /*@ 1605 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1606 values into a matrix 1607 1608 Not Collective 1609 1610 Input Parameters: 1611 + mat - the matrix 1612 . row - the (block) row to set 1613 - v - a logically two-dimensional array of values 1614 1615 Level: intermediate 1616 1617 Notes: 1618 The values, `v`, are column-oriented (for the block version) and sorted 1619 1620 All the nonzero values in `row` must be provided 1621 1622 The matrix must have previously had its column indices set, likely by having been assembled. 1623 1624 `row` must belong to this MPI process 1625 1626 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1627 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1628 @*/ 1629 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1630 { 1631 PetscInt globalrow; 1632 1633 PetscFunctionBegin; 1634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1635 PetscValidType(mat, 1); 1636 PetscAssertPointer(v, 3); 1637 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1638 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1639 PetscFunctionReturn(PETSC_SUCCESS); 1640 } 1641 1642 /*@ 1643 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1644 values into a matrix 1645 1646 Not Collective 1647 1648 Input Parameters: 1649 + mat - the matrix 1650 . row - the (block) row to set 1651 - 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 1652 1653 Level: advanced 1654 1655 Notes: 1656 The values, `v`, are column-oriented for the block version. 1657 1658 All the nonzeros in `row` must be provided 1659 1660 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1661 1662 `row` must belong to this process 1663 1664 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1665 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1666 @*/ 1667 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1668 { 1669 PetscFunctionBeginHot; 1670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1671 PetscValidType(mat, 1); 1672 MatCheckPreallocated(mat, 1); 1673 PetscAssertPointer(v, 3); 1674 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1675 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1676 mat->insertmode = INSERT_VALUES; 1677 1678 if (mat->assembled) { 1679 mat->was_assembled = PETSC_TRUE; 1680 mat->assembled = PETSC_FALSE; 1681 } 1682 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1683 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1684 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1685 PetscFunctionReturn(PETSC_SUCCESS); 1686 } 1687 1688 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1689 /*@ 1690 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1691 Using structured grid indexing 1692 1693 Not Collective 1694 1695 Input Parameters: 1696 + mat - the matrix 1697 . m - number of rows being entered 1698 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1699 . n - number of columns being entered 1700 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1701 . v - a logically two-dimensional array of values 1702 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1703 1704 Level: beginner 1705 1706 Notes: 1707 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1708 1709 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1710 options cannot be mixed without intervening calls to the assembly 1711 routines. 1712 1713 The grid coordinates are across the entire grid, not just the local portion 1714 1715 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1716 as well as in C. 1717 1718 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1719 1720 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1721 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1722 1723 The columns and rows in the stencil passed in MUST be contained within the 1724 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1725 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1726 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1727 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1728 1729 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1730 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1731 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1732 `DM_BOUNDARY_PERIODIC` boundary type. 1733 1734 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 1735 a single value per point) you can skip filling those indices. 1736 1737 Inspired by the structured grid interface to the HYPRE package 1738 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1739 1740 Efficiency Alert: 1741 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1742 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1743 1744 Fortran Note: 1745 `idxm` and `idxn` should be declared as 1746 $ MatStencil idxm(4,m),idxn(4,n) 1747 and the values inserted using 1748 .vb 1749 idxm(MatStencil_i,1) = i 1750 idxm(MatStencil_j,1) = j 1751 idxm(MatStencil_k,1) = k 1752 idxm(MatStencil_c,1) = c 1753 etc 1754 .ve 1755 1756 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1757 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1758 @*/ 1759 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1760 { 1761 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1762 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1763 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1764 1765 PetscFunctionBegin; 1766 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1768 PetscValidType(mat, 1); 1769 PetscAssertPointer(idxm, 3); 1770 PetscAssertPointer(idxn, 5); 1771 1772 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1773 jdxm = buf; 1774 jdxn = buf + m; 1775 } else { 1776 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1777 jdxm = bufm; 1778 jdxn = bufn; 1779 } 1780 for (i = 0; i < m; i++) { 1781 for (j = 0; j < 3 - sdim; j++) dxm++; 1782 tmp = *dxm++ - starts[0]; 1783 for (j = 0; j < dim - 1; j++) { 1784 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1785 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1786 } 1787 if (mat->stencil.noc) dxm++; 1788 jdxm[i] = tmp; 1789 } 1790 for (i = 0; i < n; i++) { 1791 for (j = 0; j < 3 - sdim; j++) dxn++; 1792 tmp = *dxn++ - starts[0]; 1793 for (j = 0; j < dim - 1; j++) { 1794 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1795 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1796 } 1797 if (mat->stencil.noc) dxn++; 1798 jdxn[i] = tmp; 1799 } 1800 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1801 PetscCall(PetscFree2(bufm, bufn)); 1802 PetscFunctionReturn(PETSC_SUCCESS); 1803 } 1804 1805 /*@ 1806 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1807 Using structured grid indexing 1808 1809 Not Collective 1810 1811 Input Parameters: 1812 + mat - the matrix 1813 . m - number of rows being entered 1814 . idxm - grid coordinates for matrix rows being entered 1815 . n - number of columns being entered 1816 . idxn - grid coordinates for matrix columns being entered 1817 . v - a logically two-dimensional array of values 1818 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1819 1820 Level: beginner 1821 1822 Notes: 1823 By default the values, `v`, are row-oriented and unsorted. 1824 See `MatSetOption()` for other options. 1825 1826 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1827 options cannot be mixed without intervening calls to the assembly 1828 routines. 1829 1830 The grid coordinates are across the entire grid, not just the local portion 1831 1832 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1833 as well as in C. 1834 1835 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1836 1837 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1838 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1839 1840 The columns and rows in the stencil passed in MUST be contained within the 1841 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1842 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1843 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1844 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1845 1846 Negative indices may be passed in idxm and idxn, these rows and columns are 1847 simply ignored. This allows easily inserting element stiffness matrices 1848 with homogeneous Dirichlet boundary conditions that you don't want represented 1849 in the matrix. 1850 1851 Inspired by the structured grid interface to the HYPRE package 1852 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1853 1854 Fortran Note: 1855 `idxm` and `idxn` should be declared as 1856 $ MatStencil idxm(4,m),idxn(4,n) 1857 and the values inserted using 1858 .vb 1859 idxm(MatStencil_i,1) = i 1860 idxm(MatStencil_j,1) = j 1861 idxm(MatStencil_k,1) = k 1862 etc 1863 .ve 1864 1865 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1866 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1867 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1868 @*/ 1869 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1870 { 1871 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1872 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1873 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1874 1875 PetscFunctionBegin; 1876 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1878 PetscValidType(mat, 1); 1879 PetscAssertPointer(idxm, 3); 1880 PetscAssertPointer(idxn, 5); 1881 PetscAssertPointer(v, 6); 1882 1883 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1884 jdxm = buf; 1885 jdxn = buf + m; 1886 } else { 1887 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1888 jdxm = bufm; 1889 jdxn = bufn; 1890 } 1891 for (i = 0; i < m; i++) { 1892 for (j = 0; j < 3 - sdim; j++) dxm++; 1893 tmp = *dxm++ - starts[0]; 1894 for (j = 0; j < sdim - 1; j++) { 1895 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1896 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1897 } 1898 dxm++; 1899 jdxm[i] = tmp; 1900 } 1901 for (i = 0; i < n; i++) { 1902 for (j = 0; j < 3 - sdim; j++) dxn++; 1903 tmp = *dxn++ - starts[0]; 1904 for (j = 0; j < sdim - 1; j++) { 1905 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1906 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1907 } 1908 dxn++; 1909 jdxn[i] = tmp; 1910 } 1911 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1912 PetscCall(PetscFree2(bufm, bufn)); 1913 PetscFunctionReturn(PETSC_SUCCESS); 1914 } 1915 1916 /*@ 1917 MatSetStencil - Sets the grid information for setting values into a matrix via 1918 `MatSetValuesStencil()` 1919 1920 Not Collective 1921 1922 Input Parameters: 1923 + mat - the matrix 1924 . dim - dimension of the grid 1, 2, or 3 1925 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1926 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1927 - dof - number of degrees of freedom per node 1928 1929 Level: beginner 1930 1931 Notes: 1932 Inspired by the structured grid interface to the HYPRE package 1933 (www.llnl.gov/CASC/hyper) 1934 1935 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1936 user. 1937 1938 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1939 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1940 @*/ 1941 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1942 { 1943 PetscFunctionBegin; 1944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1945 PetscAssertPointer(dims, 3); 1946 PetscAssertPointer(starts, 4); 1947 1948 mat->stencil.dim = dim + (dof > 1); 1949 for (PetscInt i = 0; i < dim; i++) { 1950 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1951 mat->stencil.starts[i] = starts[dim - i - 1]; 1952 } 1953 mat->stencil.dims[dim] = dof; 1954 mat->stencil.starts[dim] = 0; 1955 mat->stencil.noc = (PetscBool)(dof == 1); 1956 PetscFunctionReturn(PETSC_SUCCESS); 1957 } 1958 1959 /*@ 1960 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1961 1962 Not Collective 1963 1964 Input Parameters: 1965 + mat - the matrix 1966 . v - a logically two-dimensional array of values 1967 . m - the number of block rows 1968 . idxm - the global block indices 1969 . n - the number of block columns 1970 . idxn - the global block indices 1971 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1972 1973 Level: intermediate 1974 1975 Notes: 1976 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1977 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1978 1979 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1980 NOT the total number of rows/columns; for example, if the block size is 2 and 1981 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 1982 The values in `idxm` would be 1 2; that is the first index for each block divided by 1983 the block size. 1984 1985 You must call `MatSetBlockSize()` when constructing this matrix (before 1986 preallocating it). 1987 1988 By default the values, `v`, are row-oriented, so the layout of 1989 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1990 1991 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1992 options cannot be mixed without intervening calls to the assembly 1993 routines. 1994 1995 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1996 as well as in C. 1997 1998 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1999 simply ignored. This allows easily inserting element stiffness matrices 2000 with homogeneous Dirichlet boundary conditions that you don't want represented 2001 in the matrix. 2002 2003 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2004 internal searching must be done to determine where to place the 2005 data in the matrix storage space. By instead inserting blocks of 2006 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2007 reduced. 2008 2009 Example: 2010 .vb 2011 Suppose m=n=2 and block size(bs) = 2 The array is 2012 2013 1 2 | 3 4 2014 5 6 | 7 8 2015 - - - | - - - 2016 9 10 | 11 12 2017 13 14 | 15 16 2018 2019 v[] should be passed in like 2020 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2021 2022 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2023 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2024 .ve 2025 2026 Fortran Notes: 2027 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2028 .vb 2029 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2030 .ve 2031 2032 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2033 2034 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2035 @*/ 2036 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2037 { 2038 PetscFunctionBeginHot; 2039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2040 PetscValidType(mat, 1); 2041 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2042 PetscAssertPointer(idxm, 3); 2043 PetscAssertPointer(idxn, 5); 2044 MatCheckPreallocated(mat, 1); 2045 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2046 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2047 if (PetscDefined(USE_DEBUG)) { 2048 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2049 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2050 } 2051 if (PetscDefined(USE_DEBUG)) { 2052 PetscInt rbs, cbs, M, N, i; 2053 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2054 PetscCall(MatGetSize(mat, &M, &N)); 2055 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); 2056 for (i = 0; i < n; i++) 2057 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); 2058 } 2059 if (mat->assembled) { 2060 mat->was_assembled = PETSC_TRUE; 2061 mat->assembled = PETSC_FALSE; 2062 } 2063 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2064 if (mat->ops->setvaluesblocked) { 2065 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2066 } else { 2067 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2068 PetscInt i, j, bs, cbs; 2069 2070 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2071 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2072 iidxm = buf; 2073 iidxn = buf + m * bs; 2074 } else { 2075 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2076 iidxm = bufr; 2077 iidxn = bufc; 2078 } 2079 for (i = 0; i < m; i++) { 2080 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2081 } 2082 if (m != n || bs != cbs || idxm != idxn) { 2083 for (i = 0; i < n; i++) { 2084 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2085 } 2086 } else iidxn = iidxm; 2087 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2088 PetscCall(PetscFree2(bufr, bufc)); 2089 } 2090 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2091 PetscFunctionReturn(PETSC_SUCCESS); 2092 } 2093 2094 /*@ 2095 MatGetValues - Gets a block of local values from a matrix. 2096 2097 Not Collective; can only return values that are owned by the give process 2098 2099 Input Parameters: 2100 + mat - the matrix 2101 . v - a logically two-dimensional array for storing the values 2102 . m - the number of rows 2103 . idxm - the global indices of the rows 2104 . n - the number of columns 2105 - idxn - the global indices of the columns 2106 2107 Level: advanced 2108 2109 Notes: 2110 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2111 The values, `v`, are then returned in a row-oriented format, 2112 analogous to that used by default in `MatSetValues()`. 2113 2114 `MatGetValues()` uses 0-based row and column numbers in 2115 Fortran as well as in C. 2116 2117 `MatGetValues()` requires that the matrix has been assembled 2118 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2119 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2120 without intermediate matrix assembly. 2121 2122 Negative row or column indices will be ignored and those locations in `v` will be 2123 left unchanged. 2124 2125 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2126 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2127 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2128 2129 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2130 @*/ 2131 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2132 { 2133 PetscFunctionBegin; 2134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2135 PetscValidType(mat, 1); 2136 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2137 PetscAssertPointer(idxm, 3); 2138 PetscAssertPointer(idxn, 5); 2139 PetscAssertPointer(v, 6); 2140 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2141 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2142 MatCheckPreallocated(mat, 1); 2143 2144 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2145 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2146 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2147 PetscFunctionReturn(PETSC_SUCCESS); 2148 } 2149 2150 /*@ 2151 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2152 defined previously by `MatSetLocalToGlobalMapping()` 2153 2154 Not Collective 2155 2156 Input Parameters: 2157 + mat - the matrix 2158 . nrow - number of rows 2159 . irow - the row local indices 2160 . ncol - number of columns 2161 - icol - the column local indices 2162 2163 Output Parameter: 2164 . y - a logically two-dimensional array of values 2165 2166 Level: advanced 2167 2168 Notes: 2169 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2170 2171 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, 2172 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2173 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2174 with `MatSetLocalToGlobalMapping()`. 2175 2176 Developer Note: 2177 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2178 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2179 2180 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2181 `MatSetValuesLocal()`, `MatGetValues()` 2182 @*/ 2183 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2184 { 2185 PetscFunctionBeginHot; 2186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2187 PetscValidType(mat, 1); 2188 MatCheckPreallocated(mat, 1); 2189 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2190 PetscAssertPointer(irow, 3); 2191 PetscAssertPointer(icol, 5); 2192 if (PetscDefined(USE_DEBUG)) { 2193 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2194 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2195 } 2196 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2197 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2198 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2199 else { 2200 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2201 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2202 irowm = buf; 2203 icolm = buf + nrow; 2204 } else { 2205 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2206 irowm = bufr; 2207 icolm = bufc; 2208 } 2209 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2210 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2211 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2212 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2213 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2214 PetscCall(PetscFree2(bufr, bufc)); 2215 } 2216 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2217 PetscFunctionReturn(PETSC_SUCCESS); 2218 } 2219 2220 /*@ 2221 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2222 the same size. Currently, this can only be called once and creates the given matrix. 2223 2224 Not Collective 2225 2226 Input Parameters: 2227 + mat - the matrix 2228 . nb - the number of blocks 2229 . bs - the number of rows (and columns) in each block 2230 . rows - a concatenation of the rows for each block 2231 - v - a concatenation of logically two-dimensional arrays of values 2232 2233 Level: advanced 2234 2235 Notes: 2236 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2237 2238 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2239 2240 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2241 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2242 @*/ 2243 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2244 { 2245 PetscFunctionBegin; 2246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2247 PetscValidType(mat, 1); 2248 PetscAssertPointer(rows, 4); 2249 PetscAssertPointer(v, 5); 2250 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2251 2252 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2253 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2254 else { 2255 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2256 } 2257 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2258 PetscFunctionReturn(PETSC_SUCCESS); 2259 } 2260 2261 /*@ 2262 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2263 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2264 using a local (per-processor) numbering. 2265 2266 Not Collective 2267 2268 Input Parameters: 2269 + x - the matrix 2270 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2271 - cmapping - column mapping 2272 2273 Level: intermediate 2274 2275 Note: 2276 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2277 2278 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2279 @*/ 2280 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2281 { 2282 PetscFunctionBegin; 2283 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2284 PetscValidType(x, 1); 2285 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2286 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2287 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2288 else { 2289 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2290 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2291 } 2292 PetscFunctionReturn(PETSC_SUCCESS); 2293 } 2294 2295 /*@ 2296 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2297 2298 Not Collective 2299 2300 Input Parameter: 2301 . A - the matrix 2302 2303 Output Parameters: 2304 + rmapping - row mapping 2305 - cmapping - column mapping 2306 2307 Level: advanced 2308 2309 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2310 @*/ 2311 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2312 { 2313 PetscFunctionBegin; 2314 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2315 PetscValidType(A, 1); 2316 if (rmapping) { 2317 PetscAssertPointer(rmapping, 2); 2318 *rmapping = A->rmap->mapping; 2319 } 2320 if (cmapping) { 2321 PetscAssertPointer(cmapping, 3); 2322 *cmapping = A->cmap->mapping; 2323 } 2324 PetscFunctionReturn(PETSC_SUCCESS); 2325 } 2326 2327 /*@ 2328 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2329 2330 Logically Collective 2331 2332 Input Parameters: 2333 + A - the matrix 2334 . rmap - row layout 2335 - cmap - column layout 2336 2337 Level: advanced 2338 2339 Note: 2340 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2341 2342 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2343 @*/ 2344 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2345 { 2346 PetscFunctionBegin; 2347 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2348 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2349 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2350 PetscFunctionReturn(PETSC_SUCCESS); 2351 } 2352 2353 /*@ 2354 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2355 2356 Not Collective 2357 2358 Input Parameter: 2359 . A - the matrix 2360 2361 Output Parameters: 2362 + rmap - row layout 2363 - cmap - column layout 2364 2365 Level: advanced 2366 2367 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2368 @*/ 2369 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2370 { 2371 PetscFunctionBegin; 2372 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2373 PetscValidType(A, 1); 2374 if (rmap) { 2375 PetscAssertPointer(rmap, 2); 2376 *rmap = A->rmap; 2377 } 2378 if (cmap) { 2379 PetscAssertPointer(cmap, 3); 2380 *cmap = A->cmap; 2381 } 2382 PetscFunctionReturn(PETSC_SUCCESS); 2383 } 2384 2385 /*@ 2386 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2387 using a local numbering of the rows and columns. 2388 2389 Not Collective 2390 2391 Input Parameters: 2392 + mat - the matrix 2393 . nrow - number of rows 2394 . irow - the row local indices 2395 . ncol - number of columns 2396 . icol - the column local indices 2397 . y - a logically two-dimensional array of values 2398 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2399 2400 Level: intermediate 2401 2402 Notes: 2403 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2404 2405 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2406 options cannot be mixed without intervening calls to the assembly 2407 routines. 2408 2409 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2410 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2411 2412 Fortran Notes: 2413 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2414 .vb 2415 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2416 .ve 2417 2418 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2419 2420 Developer Note: 2421 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2422 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2423 2424 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2425 `MatGetValuesLocal()` 2426 @*/ 2427 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2428 { 2429 PetscFunctionBeginHot; 2430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2431 PetscValidType(mat, 1); 2432 MatCheckPreallocated(mat, 1); 2433 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2434 PetscAssertPointer(irow, 3); 2435 PetscAssertPointer(icol, 5); 2436 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2437 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2438 if (PetscDefined(USE_DEBUG)) { 2439 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2440 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2441 } 2442 2443 if (mat->assembled) { 2444 mat->was_assembled = PETSC_TRUE; 2445 mat->assembled = PETSC_FALSE; 2446 } 2447 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2448 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2449 else { 2450 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2451 const PetscInt *irowm, *icolm; 2452 2453 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2454 bufr = buf; 2455 bufc = buf + nrow; 2456 irowm = bufr; 2457 icolm = bufc; 2458 } else { 2459 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2460 irowm = bufr; 2461 icolm = bufc; 2462 } 2463 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2464 else irowm = irow; 2465 if (mat->cmap->mapping) { 2466 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2467 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2468 } else icolm = irowm; 2469 } else icolm = icol; 2470 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2471 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2472 } 2473 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2474 PetscFunctionReturn(PETSC_SUCCESS); 2475 } 2476 2477 /*@ 2478 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2479 using a local ordering of the nodes a block at a time. 2480 2481 Not Collective 2482 2483 Input Parameters: 2484 + mat - the matrix 2485 . nrow - number of rows 2486 . irow - the row local indices 2487 . ncol - number of columns 2488 . icol - the column local indices 2489 . y - a logically two-dimensional array of values 2490 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2491 2492 Level: intermediate 2493 2494 Notes: 2495 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2496 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2497 2498 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2499 options cannot be mixed without intervening calls to the assembly 2500 routines. 2501 2502 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2503 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2504 2505 Fortran Notes: 2506 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2507 .vb 2508 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2509 .ve 2510 2511 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2512 2513 Developer Note: 2514 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2515 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2516 2517 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2518 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2519 @*/ 2520 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2521 { 2522 PetscFunctionBeginHot; 2523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2524 PetscValidType(mat, 1); 2525 MatCheckPreallocated(mat, 1); 2526 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2527 PetscAssertPointer(irow, 3); 2528 PetscAssertPointer(icol, 5); 2529 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2530 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2531 if (PetscDefined(USE_DEBUG)) { 2532 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2533 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); 2534 } 2535 2536 if (mat->assembled) { 2537 mat->was_assembled = PETSC_TRUE; 2538 mat->assembled = PETSC_FALSE; 2539 } 2540 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2541 PetscInt irbs, rbs; 2542 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2543 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2544 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2545 } 2546 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2547 PetscInt icbs, cbs; 2548 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2549 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2550 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2551 } 2552 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2553 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2554 else { 2555 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2556 const PetscInt *irowm, *icolm; 2557 2558 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2559 bufr = buf; 2560 bufc = buf + nrow; 2561 irowm = bufr; 2562 icolm = bufc; 2563 } else { 2564 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2565 irowm = bufr; 2566 icolm = bufc; 2567 } 2568 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2569 else irowm = irow; 2570 if (mat->cmap->mapping) { 2571 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2572 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2573 } else icolm = irowm; 2574 } else icolm = icol; 2575 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2576 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2577 } 2578 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2579 PetscFunctionReturn(PETSC_SUCCESS); 2580 } 2581 2582 /*@ 2583 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2584 2585 Collective 2586 2587 Input Parameters: 2588 + mat - the matrix 2589 - x - the vector to be multiplied 2590 2591 Output Parameter: 2592 . y - the result 2593 2594 Level: developer 2595 2596 Note: 2597 The vectors `x` and `y` cannot be the same. I.e., one cannot 2598 call `MatMultDiagonalBlock`(A,y,y). 2599 2600 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2601 @*/ 2602 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2603 { 2604 PetscFunctionBegin; 2605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2606 PetscValidType(mat, 1); 2607 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2608 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2609 2610 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2611 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2612 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2613 MatCheckPreallocated(mat, 1); 2614 2615 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2616 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2617 PetscFunctionReturn(PETSC_SUCCESS); 2618 } 2619 2620 /*@ 2621 MatMult - Computes the matrix-vector product, $y = Ax$. 2622 2623 Neighbor-wise Collective 2624 2625 Input Parameters: 2626 + mat - the matrix 2627 - x - the vector to be multiplied 2628 2629 Output Parameter: 2630 . y - the result 2631 2632 Level: beginner 2633 2634 Note: 2635 The vectors `x` and `y` cannot be the same. I.e., one cannot 2636 call `MatMult`(A,y,y). 2637 2638 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2639 @*/ 2640 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2641 { 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2644 PetscValidType(mat, 1); 2645 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2646 VecCheckAssembled(x); 2647 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2648 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2649 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2650 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2651 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); 2652 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); 2653 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); 2654 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); 2655 PetscCall(VecSetErrorIfLocked(y, 3)); 2656 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2657 MatCheckPreallocated(mat, 1); 2658 2659 PetscCall(VecLockReadPush(x)); 2660 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2661 PetscUseTypeMethod(mat, mult, x, y); 2662 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2663 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2664 PetscCall(VecLockReadPop(x)); 2665 PetscFunctionReturn(PETSC_SUCCESS); 2666 } 2667 2668 /*@ 2669 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2670 2671 Neighbor-wise Collective 2672 2673 Input Parameters: 2674 + mat - the matrix 2675 - x - the vector to be multiplied 2676 2677 Output Parameter: 2678 . y - the result 2679 2680 Level: beginner 2681 2682 Notes: 2683 The vectors `x` and `y` cannot be the same. I.e., one cannot 2684 call `MatMultTranspose`(A,y,y). 2685 2686 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2687 use `MatMultHermitianTranspose()` 2688 2689 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2690 @*/ 2691 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2692 { 2693 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2694 2695 PetscFunctionBegin; 2696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2697 PetscValidType(mat, 1); 2698 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2699 VecCheckAssembled(x); 2700 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2701 2702 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2703 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2704 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2705 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); 2706 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); 2707 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); 2708 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); 2709 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2710 MatCheckPreallocated(mat, 1); 2711 2712 if (!mat->ops->multtranspose) { 2713 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2714 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); 2715 } else op = mat->ops->multtranspose; 2716 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2717 PetscCall(VecLockReadPush(x)); 2718 PetscCall((*op)(mat, x, y)); 2719 PetscCall(VecLockReadPop(x)); 2720 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2721 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2722 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2723 PetscFunctionReturn(PETSC_SUCCESS); 2724 } 2725 2726 /*@ 2727 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2728 2729 Neighbor-wise Collective 2730 2731 Input Parameters: 2732 + mat - the matrix 2733 - x - the vector to be multiplied 2734 2735 Output Parameter: 2736 . y - the result 2737 2738 Level: beginner 2739 2740 Notes: 2741 The vectors `x` and `y` cannot be the same. I.e., one cannot 2742 call `MatMultHermitianTranspose`(A,y,y). 2743 2744 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2745 2746 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2747 2748 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2749 @*/ 2750 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2751 { 2752 PetscFunctionBegin; 2753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2754 PetscValidType(mat, 1); 2755 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2756 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2757 2758 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2759 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2760 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2761 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); 2762 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); 2763 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); 2764 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); 2765 MatCheckPreallocated(mat, 1); 2766 2767 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2768 #if defined(PETSC_USE_COMPLEX) 2769 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2770 PetscCall(VecLockReadPush(x)); 2771 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2772 else PetscUseTypeMethod(mat, mult, x, y); 2773 PetscCall(VecLockReadPop(x)); 2774 } else { 2775 Vec w; 2776 PetscCall(VecDuplicate(x, &w)); 2777 PetscCall(VecCopy(x, w)); 2778 PetscCall(VecConjugate(w)); 2779 PetscCall(MatMultTranspose(mat, w, y)); 2780 PetscCall(VecDestroy(&w)); 2781 PetscCall(VecConjugate(y)); 2782 } 2783 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2784 #else 2785 PetscCall(MatMultTranspose(mat, x, y)); 2786 #endif 2787 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2788 PetscFunctionReturn(PETSC_SUCCESS); 2789 } 2790 2791 /*@ 2792 MatMultAdd - Computes $v3 = v2 + A * v1$. 2793 2794 Neighbor-wise Collective 2795 2796 Input Parameters: 2797 + mat - the matrix 2798 . v1 - the vector to be multiplied by `mat` 2799 - v2 - the vector to be added to the result 2800 2801 Output Parameter: 2802 . v3 - the result 2803 2804 Level: beginner 2805 2806 Note: 2807 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2808 call `MatMultAdd`(A,v1,v2,v1). 2809 2810 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2811 @*/ 2812 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2813 { 2814 PetscFunctionBegin; 2815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2816 PetscValidType(mat, 1); 2817 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2818 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2819 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2820 2821 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2822 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2823 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); 2824 /* 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); 2825 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); */ 2826 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); 2827 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); 2828 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2829 MatCheckPreallocated(mat, 1); 2830 2831 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2832 PetscCall(VecLockReadPush(v1)); 2833 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2834 PetscCall(VecLockReadPop(v1)); 2835 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2836 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2837 PetscFunctionReturn(PETSC_SUCCESS); 2838 } 2839 2840 /*@ 2841 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2842 2843 Neighbor-wise Collective 2844 2845 Input Parameters: 2846 + mat - the matrix 2847 . v1 - the vector to be multiplied by the transpose of the matrix 2848 - v2 - the vector to be added to the result 2849 2850 Output Parameter: 2851 . v3 - the result 2852 2853 Level: beginner 2854 2855 Note: 2856 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2857 call `MatMultTransposeAdd`(A,v1,v2,v1). 2858 2859 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2860 @*/ 2861 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2862 { 2863 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2864 2865 PetscFunctionBegin; 2866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2867 PetscValidType(mat, 1); 2868 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2869 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2870 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2871 2872 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2873 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2874 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); 2875 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); 2876 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); 2877 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2878 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2879 MatCheckPreallocated(mat, 1); 2880 2881 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2882 PetscCall(VecLockReadPush(v1)); 2883 PetscCall((*op)(mat, v1, v2, v3)); 2884 PetscCall(VecLockReadPop(v1)); 2885 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2886 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@ 2891 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2892 2893 Neighbor-wise Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 . v1 - the vector to be multiplied by the Hermitian transpose 2898 - v2 - the vector to be added to the result 2899 2900 Output Parameter: 2901 . v3 - the result 2902 2903 Level: beginner 2904 2905 Note: 2906 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2907 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2908 2909 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2910 @*/ 2911 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2912 { 2913 PetscFunctionBegin; 2914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2915 PetscValidType(mat, 1); 2916 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2917 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2918 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2919 2920 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2921 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2922 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2923 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); 2924 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); 2925 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); 2926 MatCheckPreallocated(mat, 1); 2927 2928 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2929 PetscCall(VecLockReadPush(v1)); 2930 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2931 else { 2932 Vec w, z; 2933 PetscCall(VecDuplicate(v1, &w)); 2934 PetscCall(VecCopy(v1, w)); 2935 PetscCall(VecConjugate(w)); 2936 PetscCall(VecDuplicate(v3, &z)); 2937 PetscCall(MatMultTranspose(mat, w, z)); 2938 PetscCall(VecDestroy(&w)); 2939 PetscCall(VecConjugate(z)); 2940 if (v2 != v3) { 2941 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2942 } else { 2943 PetscCall(VecAXPY(v3, 1.0, z)); 2944 } 2945 PetscCall(VecDestroy(&z)); 2946 } 2947 PetscCall(VecLockReadPop(v1)); 2948 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2949 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2950 PetscFunctionReturn(PETSC_SUCCESS); 2951 } 2952 2953 /*@ 2954 MatGetFactorType - gets the type of factorization a matrix is 2955 2956 Not Collective 2957 2958 Input Parameter: 2959 . mat - the matrix 2960 2961 Output Parameter: 2962 . 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` 2963 2964 Level: intermediate 2965 2966 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2967 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2968 @*/ 2969 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2970 { 2971 PetscFunctionBegin; 2972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2973 PetscValidType(mat, 1); 2974 PetscAssertPointer(t, 2); 2975 *t = mat->factortype; 2976 PetscFunctionReturn(PETSC_SUCCESS); 2977 } 2978 2979 /*@ 2980 MatSetFactorType - sets the type of factorization a matrix is 2981 2982 Logically Collective 2983 2984 Input Parameters: 2985 + mat - the matrix 2986 - 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` 2987 2988 Level: intermediate 2989 2990 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2991 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2992 @*/ 2993 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2994 { 2995 PetscFunctionBegin; 2996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2997 PetscValidType(mat, 1); 2998 mat->factortype = t; 2999 PetscFunctionReturn(PETSC_SUCCESS); 3000 } 3001 3002 /*@ 3003 MatGetInfo - Returns information about matrix storage (number of 3004 nonzeros, memory, etc.). 3005 3006 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3007 3008 Input Parameters: 3009 + mat - the matrix 3010 - 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) 3011 3012 Output Parameter: 3013 . info - matrix information context 3014 3015 Options Database Key: 3016 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3017 3018 Level: intermediate 3019 3020 Notes: 3021 The `MatInfo` context contains a variety of matrix data, including 3022 number of nonzeros allocated and used, number of mallocs during 3023 matrix assembly, etc. Additional information for factored matrices 3024 is provided (such as the fill ratio, number of mallocs during 3025 factorization, etc.). 3026 3027 Example: 3028 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3029 data within the `MatInfo` context. For example, 3030 .vb 3031 MatInfo info; 3032 Mat A; 3033 double mal, nz_a, nz_u; 3034 3035 MatGetInfo(A, MAT_LOCAL, &info); 3036 mal = info.mallocs; 3037 nz_a = info.nz_allocated; 3038 .ve 3039 3040 Fortran Note: 3041 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3042 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3043 a complete list of parameter names. 3044 .vb 3045 MatInfo info(MAT_INFO_SIZE) 3046 double precision mal, nz_a 3047 Mat A 3048 integer ierr 3049 3050 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3051 mal = info(MAT_INFO_MALLOCS) 3052 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3053 .ve 3054 3055 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3056 @*/ 3057 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3058 { 3059 PetscFunctionBegin; 3060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3061 PetscValidType(mat, 1); 3062 PetscAssertPointer(info, 3); 3063 MatCheckPreallocated(mat, 1); 3064 PetscUseTypeMethod(mat, getinfo, flag, info); 3065 PetscFunctionReturn(PETSC_SUCCESS); 3066 } 3067 3068 /* 3069 This is used by external packages where it is not easy to get the info from the actual 3070 matrix factorization. 3071 */ 3072 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3073 { 3074 PetscFunctionBegin; 3075 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3076 PetscFunctionReturn(PETSC_SUCCESS); 3077 } 3078 3079 /*@ 3080 MatLUFactor - Performs in-place LU factorization of matrix. 3081 3082 Collective 3083 3084 Input Parameters: 3085 + mat - the matrix 3086 . row - row permutation 3087 . col - column permutation 3088 - info - options for factorization, includes 3089 .vb 3090 fill - expected fill as ratio of original fill. 3091 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3092 Run with the option -info to determine an optimal value to use 3093 .ve 3094 3095 Level: developer 3096 3097 Notes: 3098 Most users should employ the `KSP` interface for linear solvers 3099 instead of working directly with matrix algebra routines such as this. 3100 See, e.g., `KSPCreate()`. 3101 3102 This changes the state of the matrix to a factored matrix; it cannot be used 3103 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3104 3105 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3106 when not using `KSP`. 3107 3108 Developer Note: 3109 The Fortran interface is not autogenerated as the 3110 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3111 3112 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3113 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3114 @*/ 3115 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3116 { 3117 MatFactorInfo tinfo; 3118 3119 PetscFunctionBegin; 3120 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3121 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3122 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3123 if (info) PetscAssertPointer(info, 4); 3124 PetscValidType(mat, 1); 3125 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3126 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3127 MatCheckPreallocated(mat, 1); 3128 if (!info) { 3129 PetscCall(MatFactorInfoInitialize(&tinfo)); 3130 info = &tinfo; 3131 } 3132 3133 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3134 PetscUseTypeMethod(mat, lufactor, row, col, info); 3135 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3136 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3137 PetscFunctionReturn(PETSC_SUCCESS); 3138 } 3139 3140 /*@ 3141 MatILUFactor - Performs in-place ILU factorization of matrix. 3142 3143 Collective 3144 3145 Input Parameters: 3146 + mat - the matrix 3147 . row - row permutation 3148 . col - column permutation 3149 - info - structure containing 3150 .vb 3151 levels - number of levels of fill. 3152 expected fill - as ratio of original fill. 3153 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3154 missing diagonal entries) 3155 .ve 3156 3157 Level: developer 3158 3159 Notes: 3160 Most users should employ the `KSP` interface for linear solvers 3161 instead of working directly with matrix algebra routines such as this. 3162 See, e.g., `KSPCreate()`. 3163 3164 Probably really in-place only when level of fill is zero, otherwise allocates 3165 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3166 when not using `KSP`. 3167 3168 Developer Note: 3169 The Fortran interface is not autogenerated as the 3170 interface definition cannot be generated correctly [due to MatFactorInfo] 3171 3172 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3173 @*/ 3174 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3175 { 3176 PetscFunctionBegin; 3177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3178 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3179 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3180 PetscAssertPointer(info, 4); 3181 PetscValidType(mat, 1); 3182 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3183 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3184 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3185 MatCheckPreallocated(mat, 1); 3186 3187 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3188 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3189 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3190 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3191 PetscFunctionReturn(PETSC_SUCCESS); 3192 } 3193 3194 /*@ 3195 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3196 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3197 3198 Collective 3199 3200 Input Parameters: 3201 + fact - the factor matrix obtained with `MatGetFactor()` 3202 . mat - the matrix 3203 . row - the row permutation 3204 . col - the column permutation 3205 - info - options for factorization, includes 3206 .vb 3207 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3208 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3209 .ve 3210 3211 Level: developer 3212 3213 Notes: 3214 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3215 3216 Most users should employ the simplified `KSP` interface for linear solvers 3217 instead of working directly with matrix algebra routines such as this. 3218 See, e.g., `KSPCreate()`. 3219 3220 Developer Note: 3221 The Fortran interface is not autogenerated as the 3222 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3223 3224 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3225 @*/ 3226 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3227 { 3228 MatFactorInfo tinfo; 3229 3230 PetscFunctionBegin; 3231 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3233 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3234 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3235 if (info) PetscAssertPointer(info, 5); 3236 PetscValidType(fact, 1); 3237 PetscValidType(mat, 2); 3238 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3239 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3240 MatCheckPreallocated(mat, 2); 3241 if (!info) { 3242 PetscCall(MatFactorInfoInitialize(&tinfo)); 3243 info = &tinfo; 3244 } 3245 3246 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3247 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3248 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3249 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3250 PetscFunctionReturn(PETSC_SUCCESS); 3251 } 3252 3253 /*@ 3254 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3255 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3256 3257 Collective 3258 3259 Input Parameters: 3260 + fact - the factor matrix obtained with `MatGetFactor()` 3261 . mat - the matrix 3262 - info - options for factorization 3263 3264 Level: developer 3265 3266 Notes: 3267 See `MatLUFactor()` for in-place factorization. See 3268 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3269 3270 Most users should employ the `KSP` interface for linear solvers 3271 instead of working directly with matrix algebra routines such as this. 3272 See, e.g., `KSPCreate()`. 3273 3274 Developer Note: 3275 The Fortran interface is not autogenerated as the 3276 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3277 3278 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3279 @*/ 3280 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3281 { 3282 MatFactorInfo tinfo; 3283 3284 PetscFunctionBegin; 3285 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3286 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3287 PetscValidType(fact, 1); 3288 PetscValidType(mat, 2); 3289 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3290 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, 3291 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3292 3293 MatCheckPreallocated(mat, 2); 3294 if (!info) { 3295 PetscCall(MatFactorInfoInitialize(&tinfo)); 3296 info = &tinfo; 3297 } 3298 3299 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3300 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3301 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3302 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3303 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3304 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3305 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3306 PetscFunctionReturn(PETSC_SUCCESS); 3307 } 3308 3309 /*@ 3310 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3311 symmetric matrix. 3312 3313 Collective 3314 3315 Input Parameters: 3316 + mat - the matrix 3317 . perm - row and column permutations 3318 - info - expected fill as ratio of original fill 3319 3320 Level: developer 3321 3322 Notes: 3323 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3324 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3325 3326 Most users should employ the `KSP` interface for linear solvers 3327 instead of working directly with matrix algebra routines such as this. 3328 See, e.g., `KSPCreate()`. 3329 3330 Developer Note: 3331 The Fortran interface is not autogenerated as the 3332 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3333 3334 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3335 `MatGetOrdering()` 3336 @*/ 3337 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3338 { 3339 MatFactorInfo tinfo; 3340 3341 PetscFunctionBegin; 3342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3343 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3344 if (info) PetscAssertPointer(info, 3); 3345 PetscValidType(mat, 1); 3346 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3347 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3348 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3349 MatCheckPreallocated(mat, 1); 3350 if (!info) { 3351 PetscCall(MatFactorInfoInitialize(&tinfo)); 3352 info = &tinfo; 3353 } 3354 3355 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3356 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3357 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3358 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3359 PetscFunctionReturn(PETSC_SUCCESS); 3360 } 3361 3362 /*@ 3363 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3364 of a symmetric matrix. 3365 3366 Collective 3367 3368 Input Parameters: 3369 + fact - the factor matrix obtained with `MatGetFactor()` 3370 . mat - the matrix 3371 . perm - row and column permutations 3372 - info - options for factorization, includes 3373 .vb 3374 fill - expected fill as ratio of original fill. 3375 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3376 Run with the option -info to determine an optimal value to use 3377 .ve 3378 3379 Level: developer 3380 3381 Notes: 3382 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3383 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3384 3385 Most users should employ the `KSP` interface for linear solvers 3386 instead of working directly with matrix algebra routines such as this. 3387 See, e.g., `KSPCreate()`. 3388 3389 Developer Note: 3390 The Fortran interface is not autogenerated as the 3391 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3392 3393 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3394 `MatGetOrdering()` 3395 @*/ 3396 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3397 { 3398 MatFactorInfo tinfo; 3399 3400 PetscFunctionBegin; 3401 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3403 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3404 if (info) PetscAssertPointer(info, 4); 3405 PetscValidType(fact, 1); 3406 PetscValidType(mat, 2); 3407 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3408 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3409 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3410 MatCheckPreallocated(mat, 2); 3411 if (!info) { 3412 PetscCall(MatFactorInfoInitialize(&tinfo)); 3413 info = &tinfo; 3414 } 3415 3416 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3417 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3418 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3419 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3420 PetscFunctionReturn(PETSC_SUCCESS); 3421 } 3422 3423 /*@ 3424 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3425 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3426 `MatCholeskyFactorSymbolic()`. 3427 3428 Collective 3429 3430 Input Parameters: 3431 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3432 . mat - the initial matrix that is to be factored 3433 - info - options for factorization 3434 3435 Level: developer 3436 3437 Note: 3438 Most users should employ the `KSP` interface for linear solvers 3439 instead of working directly with matrix algebra routines such as this. 3440 See, e.g., `KSPCreate()`. 3441 3442 Developer Note: 3443 The Fortran interface is not autogenerated as the 3444 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3445 3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3447 @*/ 3448 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3449 { 3450 MatFactorInfo tinfo; 3451 3452 PetscFunctionBegin; 3453 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3454 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3455 PetscValidType(fact, 1); 3456 PetscValidType(mat, 2); 3457 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3458 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, 3459 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3460 MatCheckPreallocated(mat, 2); 3461 if (!info) { 3462 PetscCall(MatFactorInfoInitialize(&tinfo)); 3463 info = &tinfo; 3464 } 3465 3466 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3467 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3468 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3469 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3470 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3471 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3472 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3473 PetscFunctionReturn(PETSC_SUCCESS); 3474 } 3475 3476 /*@ 3477 MatQRFactor - Performs in-place QR factorization of matrix. 3478 3479 Collective 3480 3481 Input Parameters: 3482 + mat - the matrix 3483 . col - column permutation 3484 - info - options for factorization, includes 3485 .vb 3486 fill - expected fill as ratio of original fill. 3487 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3488 Run with the option -info to determine an optimal value to use 3489 .ve 3490 3491 Level: developer 3492 3493 Notes: 3494 Most users should employ the `KSP` interface for linear solvers 3495 instead of working directly with matrix algebra routines such as this. 3496 See, e.g., `KSPCreate()`. 3497 3498 This changes the state of the matrix to a factored matrix; it cannot be used 3499 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3500 3501 Developer Note: 3502 The Fortran interface is not autogenerated as the 3503 interface definition cannot be generated correctly [due to MatFactorInfo] 3504 3505 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3506 `MatSetUnfactored()` 3507 @*/ 3508 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3509 { 3510 PetscFunctionBegin; 3511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3512 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3513 if (info) PetscAssertPointer(info, 3); 3514 PetscValidType(mat, 1); 3515 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3516 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3517 MatCheckPreallocated(mat, 1); 3518 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3519 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3520 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3521 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3522 PetscFunctionReturn(PETSC_SUCCESS); 3523 } 3524 3525 /*@ 3526 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3527 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3528 3529 Collective 3530 3531 Input Parameters: 3532 + fact - the factor matrix obtained with `MatGetFactor()` 3533 . mat - the matrix 3534 . col - column permutation 3535 - info - options for factorization, includes 3536 .vb 3537 fill - expected fill as ratio of original fill. 3538 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3539 Run with the option -info to determine an optimal value to use 3540 .ve 3541 3542 Level: developer 3543 3544 Note: 3545 Most users should employ the `KSP` interface for linear solvers 3546 instead of working directly with matrix algebra routines such as this. 3547 See, e.g., `KSPCreate()`. 3548 3549 Developer Note: 3550 The Fortran interface is not autogenerated as the 3551 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3552 3553 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3554 @*/ 3555 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3556 { 3557 MatFactorInfo tinfo; 3558 3559 PetscFunctionBegin; 3560 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3562 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3563 if (info) PetscAssertPointer(info, 4); 3564 PetscValidType(fact, 1); 3565 PetscValidType(mat, 2); 3566 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3567 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3568 MatCheckPreallocated(mat, 2); 3569 if (!info) { 3570 PetscCall(MatFactorInfoInitialize(&tinfo)); 3571 info = &tinfo; 3572 } 3573 3574 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3575 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3576 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3577 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3578 PetscFunctionReturn(PETSC_SUCCESS); 3579 } 3580 3581 /*@ 3582 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3583 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3584 3585 Collective 3586 3587 Input Parameters: 3588 + fact - the factor matrix obtained with `MatGetFactor()` 3589 . mat - the matrix 3590 - info - options for factorization 3591 3592 Level: developer 3593 3594 Notes: 3595 See `MatQRFactor()` for in-place factorization. 3596 3597 Most users should employ the `KSP` interface for linear solvers 3598 instead of working directly with matrix algebra routines such as this. 3599 See, e.g., `KSPCreate()`. 3600 3601 Developer Note: 3602 The Fortran interface is not autogenerated as the 3603 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3604 3605 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3606 @*/ 3607 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3608 { 3609 MatFactorInfo tinfo; 3610 3611 PetscFunctionBegin; 3612 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3614 PetscValidType(fact, 1); 3615 PetscValidType(mat, 2); 3616 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3617 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, 3618 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3619 3620 MatCheckPreallocated(mat, 2); 3621 if (!info) { 3622 PetscCall(MatFactorInfoInitialize(&tinfo)); 3623 info = &tinfo; 3624 } 3625 3626 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3627 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3628 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3629 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3630 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3631 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3632 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3633 PetscFunctionReturn(PETSC_SUCCESS); 3634 } 3635 3636 /*@ 3637 MatSolve - Solves $A x = b$, given a factored matrix. 3638 3639 Neighbor-wise Collective 3640 3641 Input Parameters: 3642 + mat - the factored matrix 3643 - b - the right-hand-side vector 3644 3645 Output Parameter: 3646 . x - the result vector 3647 3648 Level: developer 3649 3650 Notes: 3651 The vectors `b` and `x` cannot be the same. I.e., one cannot 3652 call `MatSolve`(A,x,x). 3653 3654 Most users should employ the `KSP` interface for linear solvers 3655 instead of working directly with matrix algebra routines such as this. 3656 See, e.g., `KSPCreate()`. 3657 3658 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3659 @*/ 3660 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3661 { 3662 PetscFunctionBegin; 3663 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3664 PetscValidType(mat, 1); 3665 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3666 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3667 PetscCheckSameComm(mat, 1, b, 2); 3668 PetscCheckSameComm(mat, 1, x, 3); 3669 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3670 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); 3671 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); 3672 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); 3673 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3674 MatCheckPreallocated(mat, 1); 3675 3676 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3677 PetscCall(VecFlag(x, mat->factorerrortype)); 3678 if (mat->factorerrortype) { 3679 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3680 } else PetscUseTypeMethod(mat, solve, b, x); 3681 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3682 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3683 PetscFunctionReturn(PETSC_SUCCESS); 3684 } 3685 3686 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3687 { 3688 Vec b, x; 3689 PetscInt N, i; 3690 PetscErrorCode (*f)(Mat, Vec, Vec); 3691 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3692 3693 PetscFunctionBegin; 3694 if (A->factorerrortype) { 3695 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3696 PetscCall(MatSetInf(X)); 3697 PetscFunctionReturn(PETSC_SUCCESS); 3698 } 3699 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3700 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3701 PetscCall(MatBoundToCPU(A, &Abound)); 3702 if (!Abound) { 3703 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3704 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3705 } 3706 #if PetscDefined(HAVE_CUDA) 3707 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3708 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3709 #elif PetscDefined(HAVE_HIP) 3710 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3711 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3712 #endif 3713 PetscCall(MatGetSize(B, NULL, &N)); 3714 for (i = 0; i < N; i++) { 3715 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3716 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3717 PetscCall((*f)(A, b, x)); 3718 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3719 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3720 } 3721 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3722 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3723 PetscFunctionReturn(PETSC_SUCCESS); 3724 } 3725 3726 /*@ 3727 MatMatSolve - Solves $A X = B$, given a factored matrix. 3728 3729 Neighbor-wise Collective 3730 3731 Input Parameters: 3732 + A - the factored matrix 3733 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3734 3735 Output Parameter: 3736 . X - the result matrix (dense matrix) 3737 3738 Level: developer 3739 3740 Note: 3741 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3742 otherwise, `B` and `X` cannot be the same. 3743 3744 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3745 @*/ 3746 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3747 { 3748 PetscFunctionBegin; 3749 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3750 PetscValidType(A, 1); 3751 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3752 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3753 PetscCheckSameComm(A, 1, B, 2); 3754 PetscCheckSameComm(A, 1, X, 3); 3755 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); 3756 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); 3757 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"); 3758 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3759 MatCheckPreallocated(A, 1); 3760 3761 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3762 if (!A->ops->matsolve) { 3763 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3764 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3765 } else PetscUseTypeMethod(A, matsolve, B, X); 3766 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3767 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3768 PetscFunctionReturn(PETSC_SUCCESS); 3769 } 3770 3771 /*@ 3772 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3773 3774 Neighbor-wise Collective 3775 3776 Input Parameters: 3777 + A - the factored matrix 3778 - B - the right-hand-side matrix (`MATDENSE` matrix) 3779 3780 Output Parameter: 3781 . X - the result matrix (dense matrix) 3782 3783 Level: developer 3784 3785 Note: 3786 The matrices `B` and `X` cannot be the same. I.e., one cannot 3787 call `MatMatSolveTranspose`(A,X,X). 3788 3789 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3790 @*/ 3791 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3792 { 3793 PetscFunctionBegin; 3794 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3795 PetscValidType(A, 1); 3796 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3797 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3798 PetscCheckSameComm(A, 1, B, 2); 3799 PetscCheckSameComm(A, 1, X, 3); 3800 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3801 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); 3802 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); 3803 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); 3804 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"); 3805 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3806 MatCheckPreallocated(A, 1); 3807 3808 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3809 if (!A->ops->matsolvetranspose) { 3810 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3811 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3812 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3813 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3814 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3815 PetscFunctionReturn(PETSC_SUCCESS); 3816 } 3817 3818 /*@ 3819 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3820 3821 Neighbor-wise Collective 3822 3823 Input Parameters: 3824 + A - the factored matrix 3825 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3826 3827 Output Parameter: 3828 . X - the result matrix (dense matrix) 3829 3830 Level: developer 3831 3832 Note: 3833 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 3834 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3835 3836 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3837 @*/ 3838 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3839 { 3840 PetscFunctionBegin; 3841 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3842 PetscValidType(A, 1); 3843 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3844 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3845 PetscCheckSameComm(A, 1, Bt, 2); 3846 PetscCheckSameComm(A, 1, X, 3); 3847 3848 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3849 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); 3850 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); 3851 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"); 3852 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3853 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3854 MatCheckPreallocated(A, 1); 3855 3856 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3857 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3858 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3859 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3860 PetscFunctionReturn(PETSC_SUCCESS); 3861 } 3862 3863 /*@ 3864 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3865 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3866 3867 Neighbor-wise Collective 3868 3869 Input Parameters: 3870 + mat - the factored matrix 3871 - b - the right-hand-side vector 3872 3873 Output Parameter: 3874 . x - the result vector 3875 3876 Level: developer 3877 3878 Notes: 3879 `MatSolve()` should be used for most applications, as it performs 3880 a forward solve followed by a backward solve. 3881 3882 The vectors `b` and `x` cannot be the same, i.e., one cannot 3883 call `MatForwardSolve`(A,x,x). 3884 3885 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3886 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3887 `MatForwardSolve()` solves $U^T*D y = b$, and 3888 `MatBackwardSolve()` solves $U x = y$. 3889 Thus they do not provide a symmetric preconditioner. 3890 3891 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3892 @*/ 3893 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3894 { 3895 PetscFunctionBegin; 3896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3897 PetscValidType(mat, 1); 3898 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3899 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3900 PetscCheckSameComm(mat, 1, b, 2); 3901 PetscCheckSameComm(mat, 1, x, 3); 3902 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3903 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); 3904 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); 3905 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); 3906 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3907 MatCheckPreallocated(mat, 1); 3908 3909 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3910 PetscUseTypeMethod(mat, forwardsolve, b, x); 3911 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3912 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3913 PetscFunctionReturn(PETSC_SUCCESS); 3914 } 3915 3916 /*@ 3917 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3918 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3919 3920 Neighbor-wise Collective 3921 3922 Input Parameters: 3923 + mat - the factored matrix 3924 - b - the right-hand-side vector 3925 3926 Output Parameter: 3927 . x - the result vector 3928 3929 Level: developer 3930 3931 Notes: 3932 `MatSolve()` should be used for most applications, as it performs 3933 a forward solve followed by a backward solve. 3934 3935 The vectors `b` and `x` cannot be the same. I.e., one cannot 3936 call `MatBackwardSolve`(A,x,x). 3937 3938 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3939 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3940 `MatForwardSolve()` solves $U^T*D y = b$, and 3941 `MatBackwardSolve()` solves $U x = y$. 3942 Thus they do not provide a symmetric preconditioner. 3943 3944 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3945 @*/ 3946 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3947 { 3948 PetscFunctionBegin; 3949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3950 PetscValidType(mat, 1); 3951 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3952 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3953 PetscCheckSameComm(mat, 1, b, 2); 3954 PetscCheckSameComm(mat, 1, x, 3); 3955 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3956 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); 3957 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); 3958 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); 3959 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3960 MatCheckPreallocated(mat, 1); 3961 3962 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3963 PetscUseTypeMethod(mat, backwardsolve, b, x); 3964 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3965 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3966 PetscFunctionReturn(PETSC_SUCCESS); 3967 } 3968 3969 /*@ 3970 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3971 3972 Neighbor-wise Collective 3973 3974 Input Parameters: 3975 + mat - the factored matrix 3976 . b - the right-hand-side vector 3977 - y - the vector to be added to 3978 3979 Output Parameter: 3980 . x - the result vector 3981 3982 Level: developer 3983 3984 Note: 3985 The vectors `b` and `x` cannot be the same. I.e., one cannot 3986 call `MatSolveAdd`(A,x,y,x). 3987 3988 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3989 @*/ 3990 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3991 { 3992 PetscScalar one = 1.0; 3993 Vec tmp; 3994 3995 PetscFunctionBegin; 3996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3997 PetscValidType(mat, 1); 3998 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3999 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4000 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4001 PetscCheckSameComm(mat, 1, b, 2); 4002 PetscCheckSameComm(mat, 1, y, 3); 4003 PetscCheckSameComm(mat, 1, x, 4); 4004 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4005 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); 4006 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); 4007 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); 4008 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); 4009 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); 4010 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4011 MatCheckPreallocated(mat, 1); 4012 4013 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4014 PetscCall(VecFlag(x, mat->factorerrortype)); 4015 if (mat->factorerrortype) { 4016 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4017 } else if (mat->ops->solveadd) { 4018 PetscUseTypeMethod(mat, solveadd, b, y, x); 4019 } else { 4020 /* do the solve then the add manually */ 4021 if (x != y) { 4022 PetscCall(MatSolve(mat, b, x)); 4023 PetscCall(VecAXPY(x, one, y)); 4024 } else { 4025 PetscCall(VecDuplicate(x, &tmp)); 4026 PetscCall(VecCopy(x, tmp)); 4027 PetscCall(MatSolve(mat, b, x)); 4028 PetscCall(VecAXPY(x, one, tmp)); 4029 PetscCall(VecDestroy(&tmp)); 4030 } 4031 } 4032 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4033 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4034 PetscFunctionReturn(PETSC_SUCCESS); 4035 } 4036 4037 /*@ 4038 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4039 4040 Neighbor-wise Collective 4041 4042 Input Parameters: 4043 + mat - the factored matrix 4044 - b - the right-hand-side vector 4045 4046 Output Parameter: 4047 . x - the result vector 4048 4049 Level: developer 4050 4051 Notes: 4052 The vectors `b` and `x` cannot be the same. I.e., one cannot 4053 call `MatSolveTranspose`(A,x,x). 4054 4055 Most users should employ the `KSP` interface for linear solvers 4056 instead of working directly with matrix algebra routines such as this. 4057 See, e.g., `KSPCreate()`. 4058 4059 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4060 @*/ 4061 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4062 { 4063 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4064 4065 PetscFunctionBegin; 4066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4067 PetscValidType(mat, 1); 4068 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4069 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4070 PetscCheckSameComm(mat, 1, b, 2); 4071 PetscCheckSameComm(mat, 1, x, 3); 4072 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4073 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); 4074 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); 4075 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4076 MatCheckPreallocated(mat, 1); 4077 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4078 PetscCall(VecFlag(x, mat->factorerrortype)); 4079 if (mat->factorerrortype) { 4080 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4081 } else { 4082 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4083 PetscCall((*f)(mat, b, x)); 4084 } 4085 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4086 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4087 PetscFunctionReturn(PETSC_SUCCESS); 4088 } 4089 4090 /*@ 4091 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4092 factored matrix. 4093 4094 Neighbor-wise Collective 4095 4096 Input Parameters: 4097 + mat - the factored matrix 4098 . b - the right-hand-side vector 4099 - y - the vector to be added to 4100 4101 Output Parameter: 4102 . x - the result vector 4103 4104 Level: developer 4105 4106 Note: 4107 The vectors `b` and `x` cannot be the same. I.e., one cannot 4108 call `MatSolveTransposeAdd`(A,x,y,x). 4109 4110 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4111 @*/ 4112 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4113 { 4114 PetscScalar one = 1.0; 4115 Vec tmp; 4116 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4117 4118 PetscFunctionBegin; 4119 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4120 PetscValidType(mat, 1); 4121 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4122 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4123 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4124 PetscCheckSameComm(mat, 1, b, 2); 4125 PetscCheckSameComm(mat, 1, y, 3); 4126 PetscCheckSameComm(mat, 1, x, 4); 4127 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4128 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); 4129 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); 4130 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); 4131 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); 4132 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4133 MatCheckPreallocated(mat, 1); 4134 4135 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4136 PetscCall(VecFlag(x, mat->factorerrortype)); 4137 if (mat->factorerrortype) { 4138 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4139 } else if (f) { 4140 PetscCall((*f)(mat, b, y, x)); 4141 } else { 4142 /* do the solve then the add manually */ 4143 if (x != y) { 4144 PetscCall(MatSolveTranspose(mat, b, x)); 4145 PetscCall(VecAXPY(x, one, y)); 4146 } else { 4147 PetscCall(VecDuplicate(x, &tmp)); 4148 PetscCall(VecCopy(x, tmp)); 4149 PetscCall(MatSolveTranspose(mat, b, x)); 4150 PetscCall(VecAXPY(x, one, tmp)); 4151 PetscCall(VecDestroy(&tmp)); 4152 } 4153 } 4154 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4155 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4156 PetscFunctionReturn(PETSC_SUCCESS); 4157 } 4158 4159 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4160 /*@ 4161 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4162 4163 Neighbor-wise Collective 4164 4165 Input Parameters: 4166 + mat - the matrix 4167 . b - the right-hand side 4168 . omega - the relaxation factor 4169 . flag - flag indicating the type of SOR (see below) 4170 . shift - diagonal shift 4171 . its - the number of iterations 4172 - lits - the number of local iterations 4173 4174 Output Parameter: 4175 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4176 4177 SOR Flags: 4178 + `SOR_FORWARD_SWEEP` - forward SOR 4179 . `SOR_BACKWARD_SWEEP` - backward SOR 4180 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4181 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4182 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4183 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4184 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4185 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4186 upper/lower triangular part of matrix to 4187 vector (with omega) 4188 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4189 4190 Level: developer 4191 4192 Notes: 4193 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4194 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4195 on each processor. 4196 4197 Application programmers will not generally use `MatSOR()` directly, 4198 but instead will employ the `KSP`/`PC` interface. 4199 4200 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4201 4202 Most users should employ the `KSP` interface for linear solvers 4203 instead of working directly with matrix algebra routines such as this. 4204 See, e.g., `KSPCreate()`. 4205 4206 Vectors `x` and `b` CANNOT be the same 4207 4208 The flags are implemented as bitwise inclusive or operations. 4209 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4210 to specify a zero initial guess for SSOR. 4211 4212 Developer Note: 4213 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4214 4215 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4216 @*/ 4217 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4218 { 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4221 PetscValidType(mat, 1); 4222 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4223 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4224 PetscCheckSameComm(mat, 1, b, 2); 4225 PetscCheckSameComm(mat, 1, x, 8); 4226 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4227 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4228 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); 4229 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); 4230 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); 4231 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4232 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4233 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4234 4235 MatCheckPreallocated(mat, 1); 4236 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4237 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4238 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4239 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4240 PetscFunctionReturn(PETSC_SUCCESS); 4241 } 4242 4243 /* 4244 Default matrix copy routine. 4245 */ 4246 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4247 { 4248 PetscInt i, rstart = 0, rend = 0, nz; 4249 const PetscInt *cwork; 4250 const PetscScalar *vwork; 4251 4252 PetscFunctionBegin; 4253 if (B->assembled) PetscCall(MatZeroEntries(B)); 4254 if (str == SAME_NONZERO_PATTERN) { 4255 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4256 for (i = rstart; i < rend; i++) { 4257 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4258 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4259 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4260 } 4261 } else { 4262 PetscCall(MatAYPX(B, 0.0, A, str)); 4263 } 4264 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4265 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4266 PetscFunctionReturn(PETSC_SUCCESS); 4267 } 4268 4269 /*@ 4270 MatCopy - Copies a matrix to another matrix. 4271 4272 Collective 4273 4274 Input Parameters: 4275 + A - the matrix 4276 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4277 4278 Output Parameter: 4279 . B - where the copy is put 4280 4281 Level: intermediate 4282 4283 Notes: 4284 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4285 4286 `MatCopy()` copies the matrix entries of a matrix to another existing 4287 matrix (after first zeroing the second matrix). A related routine is 4288 `MatConvert()`, which first creates a new matrix and then copies the data. 4289 4290 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4291 @*/ 4292 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4293 { 4294 PetscInt i; 4295 4296 PetscFunctionBegin; 4297 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4298 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4299 PetscValidType(A, 1); 4300 PetscValidType(B, 2); 4301 PetscCheckSameComm(A, 1, B, 2); 4302 MatCheckPreallocated(B, 2); 4303 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4304 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4305 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, 4306 A->cmap->N, B->cmap->N); 4307 MatCheckPreallocated(A, 1); 4308 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4309 4310 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4311 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4312 else PetscCall(MatCopy_Basic(A, B, str)); 4313 4314 B->stencil.dim = A->stencil.dim; 4315 B->stencil.noc = A->stencil.noc; 4316 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4317 B->stencil.dims[i] = A->stencil.dims[i]; 4318 B->stencil.starts[i] = A->stencil.starts[i]; 4319 } 4320 4321 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4322 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4323 PetscFunctionReturn(PETSC_SUCCESS); 4324 } 4325 4326 /*@ 4327 MatConvert - Converts a matrix to another matrix, either of the same 4328 or different type. 4329 4330 Collective 4331 4332 Input Parameters: 4333 + mat - the matrix 4334 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4335 same type as the original matrix. 4336 - reuse - denotes if the destination matrix is to be created or reused. 4337 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 4338 `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). 4339 4340 Output Parameter: 4341 . M - pointer to place new matrix 4342 4343 Level: intermediate 4344 4345 Notes: 4346 `MatConvert()` first creates a new matrix and then copies the data from 4347 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4348 entries of one matrix to another already existing matrix context. 4349 4350 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4351 the MPI communicator of the generated matrix is always the same as the communicator 4352 of the input matrix. 4353 4354 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4355 @*/ 4356 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4357 { 4358 PetscBool sametype, issame, flg; 4359 PetscBool3 issymmetric, ishermitian; 4360 char convname[256], mtype[256]; 4361 Mat B; 4362 4363 PetscFunctionBegin; 4364 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4365 PetscValidType(mat, 1); 4366 PetscAssertPointer(M, 4); 4367 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4368 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4369 MatCheckPreallocated(mat, 1); 4370 4371 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4372 if (flg) newtype = mtype; 4373 4374 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4375 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4376 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4377 if (reuse == MAT_REUSE_MATRIX) { 4378 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4379 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4380 } 4381 4382 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4383 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4384 PetscFunctionReturn(PETSC_SUCCESS); 4385 } 4386 4387 /* Cache Mat options because some converters use MatHeaderReplace */ 4388 issymmetric = mat->symmetric; 4389 ishermitian = mat->hermitian; 4390 4391 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4392 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4393 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4394 } else { 4395 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4396 const char *prefix[3] = {"seq", "mpi", ""}; 4397 PetscInt i; 4398 /* 4399 Order of precedence: 4400 0) See if newtype is a superclass of the current matrix. 4401 1) See if a specialized converter is known to the current matrix. 4402 2) See if a specialized converter is known to the desired matrix class. 4403 3) See if a good general converter is registered for the desired class 4404 (as of 6/27/03 only MATMPIADJ falls into this category). 4405 4) See if a good general converter is known for the current matrix. 4406 5) Use a really basic converter. 4407 */ 4408 4409 /* 0) See if newtype is a superclass of the current matrix. 4410 i.e mat is mpiaij and newtype is aij */ 4411 for (i = 0; i < 2; i++) { 4412 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4413 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4414 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4415 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4416 if (flg) { 4417 if (reuse == MAT_INPLACE_MATRIX) { 4418 PetscCall(PetscInfo(mat, "Early return\n")); 4419 PetscFunctionReturn(PETSC_SUCCESS); 4420 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4421 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4422 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4423 PetscFunctionReturn(PETSC_SUCCESS); 4424 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4425 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4426 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4427 PetscFunctionReturn(PETSC_SUCCESS); 4428 } 4429 } 4430 } 4431 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4432 for (i = 0; i < 3; i++) { 4433 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4434 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4435 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4436 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4437 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4438 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4439 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4440 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4441 if (conv) goto foundconv; 4442 } 4443 4444 /* 2) See if a specialized converter is known to the desired matrix class. */ 4445 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4446 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4447 PetscCall(MatSetType(B, newtype)); 4448 for (i = 0; i < 3; i++) { 4449 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4450 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4451 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4452 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4453 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4454 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4455 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4456 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4457 if (conv) { 4458 PetscCall(MatDestroy(&B)); 4459 goto foundconv; 4460 } 4461 } 4462 4463 /* 3) See if a good general converter is registered for the desired class */ 4464 conv = B->ops->convertfrom; 4465 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4466 PetscCall(MatDestroy(&B)); 4467 if (conv) goto foundconv; 4468 4469 /* 4) See if a good general converter is known for the current matrix */ 4470 if (mat->ops->convert) conv = mat->ops->convert; 4471 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4472 if (conv) goto foundconv; 4473 4474 /* 5) Use a really basic converter. */ 4475 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4476 conv = MatConvert_Basic; 4477 4478 foundconv: 4479 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4480 PetscCall((*conv)(mat, newtype, reuse, M)); 4481 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4482 /* the block sizes must be same if the mappings are copied over */ 4483 (*M)->rmap->bs = mat->rmap->bs; 4484 (*M)->cmap->bs = mat->cmap->bs; 4485 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4486 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4487 (*M)->rmap->mapping = mat->rmap->mapping; 4488 (*M)->cmap->mapping = mat->cmap->mapping; 4489 } 4490 (*M)->stencil.dim = mat->stencil.dim; 4491 (*M)->stencil.noc = mat->stencil.noc; 4492 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4493 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4494 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4495 } 4496 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4497 } 4498 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4499 4500 /* Copy Mat options */ 4501 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4502 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4503 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4504 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4505 PetscFunctionReturn(PETSC_SUCCESS); 4506 } 4507 4508 /*@ 4509 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4510 4511 Not Collective 4512 4513 Input Parameter: 4514 . mat - the matrix, must be a factored matrix 4515 4516 Output Parameter: 4517 . type - the string name of the package (do not free this string) 4518 4519 Level: intermediate 4520 4521 Fortran Note: 4522 Pass in an empty string that is long enough and the package name will be copied into it. 4523 4524 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4525 @*/ 4526 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4527 { 4528 PetscErrorCode (*conv)(Mat, MatSolverType *); 4529 4530 PetscFunctionBegin; 4531 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4532 PetscValidType(mat, 1); 4533 PetscAssertPointer(type, 2); 4534 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4535 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4536 if (conv) PetscCall((*conv)(mat, type)); 4537 else *type = MATSOLVERPETSC; 4538 PetscFunctionReturn(PETSC_SUCCESS); 4539 } 4540 4541 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4542 struct _MatSolverTypeForSpecifcType { 4543 MatType mtype; 4544 /* no entry for MAT_FACTOR_NONE */ 4545 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4546 MatSolverTypeForSpecifcType next; 4547 }; 4548 4549 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4550 struct _MatSolverTypeHolder { 4551 char *name; 4552 MatSolverTypeForSpecifcType handlers; 4553 MatSolverTypeHolder next; 4554 }; 4555 4556 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4557 4558 /*@C 4559 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4560 4561 Logically Collective, No Fortran Support 4562 4563 Input Parameters: 4564 + package - name of the package, for example petsc or superlu 4565 . mtype - the matrix type that works with this package 4566 . ftype - the type of factorization supported by the package 4567 - createfactor - routine that will create the factored matrix ready to be used 4568 4569 Level: developer 4570 4571 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4572 `MatGetFactor()` 4573 @*/ 4574 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4575 { 4576 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4577 PetscBool flg; 4578 MatSolverTypeForSpecifcType inext, iprev = NULL; 4579 4580 PetscFunctionBegin; 4581 PetscCall(MatInitializePackage()); 4582 if (!next) { 4583 PetscCall(PetscNew(&MatSolverTypeHolders)); 4584 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4585 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4586 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4587 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4588 PetscFunctionReturn(PETSC_SUCCESS); 4589 } 4590 while (next) { 4591 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4592 if (flg) { 4593 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4594 inext = next->handlers; 4595 while (inext) { 4596 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4597 if (flg) { 4598 inext->createfactor[(int)ftype - 1] = createfactor; 4599 PetscFunctionReturn(PETSC_SUCCESS); 4600 } 4601 iprev = inext; 4602 inext = inext->next; 4603 } 4604 PetscCall(PetscNew(&iprev->next)); 4605 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4606 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4607 PetscFunctionReturn(PETSC_SUCCESS); 4608 } 4609 prev = next; 4610 next = next->next; 4611 } 4612 PetscCall(PetscNew(&prev->next)); 4613 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4614 PetscCall(PetscNew(&prev->next->handlers)); 4615 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4616 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4617 PetscFunctionReturn(PETSC_SUCCESS); 4618 } 4619 4620 /*@C 4621 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4622 4623 Input Parameters: 4624 + 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 4625 . ftype - the type of factorization supported by the type 4626 - mtype - the matrix type that works with this type 4627 4628 Output Parameters: 4629 + foundtype - `PETSC_TRUE` if the type was registered 4630 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4631 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4632 4633 Calling sequence of `createfactor`: 4634 + A - the matrix providing the factor matrix 4635 . ftype - the `MatFactorType` of the factor requested 4636 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4637 4638 Level: developer 4639 4640 Note: 4641 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4642 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4643 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4644 4645 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4646 `MatInitializePackage()` 4647 @*/ 4648 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4649 { 4650 MatSolverTypeHolder next = MatSolverTypeHolders; 4651 PetscBool flg; 4652 MatSolverTypeForSpecifcType inext; 4653 4654 PetscFunctionBegin; 4655 if (foundtype) *foundtype = PETSC_FALSE; 4656 if (foundmtype) *foundmtype = PETSC_FALSE; 4657 if (createfactor) *createfactor = NULL; 4658 4659 if (type) { 4660 while (next) { 4661 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4662 if (flg) { 4663 if (foundtype) *foundtype = PETSC_TRUE; 4664 inext = next->handlers; 4665 while (inext) { 4666 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4667 if (flg) { 4668 if (foundmtype) *foundmtype = PETSC_TRUE; 4669 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4670 PetscFunctionReturn(PETSC_SUCCESS); 4671 } 4672 inext = inext->next; 4673 } 4674 } 4675 next = next->next; 4676 } 4677 } else { 4678 while (next) { 4679 inext = next->handlers; 4680 while (inext) { 4681 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4682 if (flg && inext->createfactor[(int)ftype - 1]) { 4683 if (foundtype) *foundtype = PETSC_TRUE; 4684 if (foundmtype) *foundmtype = PETSC_TRUE; 4685 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4686 PetscFunctionReturn(PETSC_SUCCESS); 4687 } 4688 inext = inext->next; 4689 } 4690 next = next->next; 4691 } 4692 /* try with base classes inext->mtype */ 4693 next = MatSolverTypeHolders; 4694 while (next) { 4695 inext = next->handlers; 4696 while (inext) { 4697 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4698 if (flg && inext->createfactor[(int)ftype - 1]) { 4699 if (foundtype) *foundtype = PETSC_TRUE; 4700 if (foundmtype) *foundmtype = PETSC_TRUE; 4701 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4702 PetscFunctionReturn(PETSC_SUCCESS); 4703 } 4704 inext = inext->next; 4705 } 4706 next = next->next; 4707 } 4708 } 4709 PetscFunctionReturn(PETSC_SUCCESS); 4710 } 4711 4712 PetscErrorCode MatSolverTypeDestroy(void) 4713 { 4714 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4715 MatSolverTypeForSpecifcType inext, iprev; 4716 4717 PetscFunctionBegin; 4718 while (next) { 4719 PetscCall(PetscFree(next->name)); 4720 inext = next->handlers; 4721 while (inext) { 4722 PetscCall(PetscFree(inext->mtype)); 4723 iprev = inext; 4724 inext = inext->next; 4725 PetscCall(PetscFree(iprev)); 4726 } 4727 prev = next; 4728 next = next->next; 4729 PetscCall(PetscFree(prev)); 4730 } 4731 MatSolverTypeHolders = NULL; 4732 PetscFunctionReturn(PETSC_SUCCESS); 4733 } 4734 4735 /*@ 4736 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4737 4738 Logically Collective 4739 4740 Input Parameter: 4741 . mat - the matrix 4742 4743 Output Parameter: 4744 . flg - `PETSC_TRUE` if uses the ordering 4745 4746 Level: developer 4747 4748 Note: 4749 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4750 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4751 4752 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4753 @*/ 4754 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4755 { 4756 PetscFunctionBegin; 4757 *flg = mat->canuseordering; 4758 PetscFunctionReturn(PETSC_SUCCESS); 4759 } 4760 4761 /*@ 4762 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4763 4764 Logically Collective 4765 4766 Input Parameters: 4767 + mat - the matrix obtained with `MatGetFactor()` 4768 - ftype - the factorization type to be used 4769 4770 Output Parameter: 4771 . otype - the preferred ordering type 4772 4773 Level: developer 4774 4775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4776 @*/ 4777 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4778 { 4779 PetscFunctionBegin; 4780 *otype = mat->preferredordering[ftype]; 4781 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4782 PetscFunctionReturn(PETSC_SUCCESS); 4783 } 4784 4785 /*@ 4786 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4787 4788 Collective 4789 4790 Input Parameters: 4791 + mat - the matrix 4792 . 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 4793 the other criteria is returned 4794 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4795 4796 Output Parameter: 4797 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4798 4799 Options Database Keys: 4800 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4801 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4802 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4803 4804 Level: intermediate 4805 4806 Notes: 4807 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4808 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4809 4810 Users usually access the factorization solvers via `KSP` 4811 4812 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4813 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 4814 4815 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4816 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4817 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4818 4819 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4820 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4821 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4822 4823 Developer Note: 4824 This should actually be called `MatCreateFactor()` since it creates a new factor object 4825 4826 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4827 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4828 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4829 @*/ 4830 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4831 { 4832 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4833 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4834 4835 PetscFunctionBegin; 4836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4837 PetscValidType(mat, 1); 4838 4839 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4840 MatCheckPreallocated(mat, 1); 4841 4842 PetscCall(MatIsShell(mat, &shell)); 4843 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4844 if (hasop) { 4845 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4846 PetscFunctionReturn(PETSC_SUCCESS); 4847 } 4848 4849 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4850 if (!foundtype) { 4851 if (type) { 4852 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], 4853 ((PetscObject)mat)->type_name, type); 4854 } else { 4855 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); 4856 } 4857 } 4858 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4859 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); 4860 4861 PetscCall((*conv)(mat, ftype, f)); 4862 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4863 PetscFunctionReturn(PETSC_SUCCESS); 4864 } 4865 4866 /*@ 4867 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4868 4869 Not Collective 4870 4871 Input Parameters: 4872 + mat - the matrix 4873 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4874 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4875 4876 Output Parameter: 4877 . flg - PETSC_TRUE if the factorization is available 4878 4879 Level: intermediate 4880 4881 Notes: 4882 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4883 such as pastix, superlu, mumps etc. 4884 4885 PETSc must have been ./configure to use the external solver, using the option --download-package 4886 4887 Developer Note: 4888 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4889 4890 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4891 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4892 @*/ 4893 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4894 { 4895 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4896 4897 PetscFunctionBegin; 4898 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4899 PetscAssertPointer(flg, 4); 4900 4901 *flg = PETSC_FALSE; 4902 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4903 4904 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4905 MatCheckPreallocated(mat, 1); 4906 4907 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4908 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4909 PetscFunctionReturn(PETSC_SUCCESS); 4910 } 4911 4912 /*@ 4913 MatDuplicate - Duplicates a matrix including the non-zero structure. 4914 4915 Collective 4916 4917 Input Parameters: 4918 + mat - the matrix 4919 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4920 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4921 4922 Output Parameter: 4923 . M - pointer to place new matrix 4924 4925 Level: intermediate 4926 4927 Notes: 4928 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4929 4930 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4931 4932 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. 4933 4934 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4935 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4936 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4937 4938 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4939 @*/ 4940 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4941 { 4942 Mat B; 4943 VecType vtype; 4944 PetscInt i; 4945 PetscObject dm, container_h, container_d; 4946 void (*viewf)(void); 4947 4948 PetscFunctionBegin; 4949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4950 PetscValidType(mat, 1); 4951 PetscAssertPointer(M, 3); 4952 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4953 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4954 MatCheckPreallocated(mat, 1); 4955 4956 *M = NULL; 4957 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4958 PetscUseTypeMethod(mat, duplicate, op, M); 4959 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4960 B = *M; 4961 4962 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4963 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4964 PetscCall(MatGetVecType(mat, &vtype)); 4965 PetscCall(MatSetVecType(B, vtype)); 4966 4967 B->stencil.dim = mat->stencil.dim; 4968 B->stencil.noc = mat->stencil.noc; 4969 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4970 B->stencil.dims[i] = mat->stencil.dims[i]; 4971 B->stencil.starts[i] = mat->stencil.starts[i]; 4972 } 4973 4974 B->nooffproczerorows = mat->nooffproczerorows; 4975 B->nooffprocentries = mat->nooffprocentries; 4976 4977 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4978 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4979 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4980 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4981 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4982 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4983 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4984 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4985 PetscFunctionReturn(PETSC_SUCCESS); 4986 } 4987 4988 /*@ 4989 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4990 4991 Logically Collective 4992 4993 Input Parameter: 4994 . mat - the matrix 4995 4996 Output Parameter: 4997 . v - the diagonal of the matrix 4998 4999 Level: intermediate 5000 5001 Note: 5002 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5003 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5004 is larger than `ndiag`, the values of the remaining entries are unspecified. 5005 5006 Currently only correct in parallel for square matrices. 5007 5008 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5009 @*/ 5010 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5011 { 5012 PetscFunctionBegin; 5013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5014 PetscValidType(mat, 1); 5015 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5016 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5017 MatCheckPreallocated(mat, 1); 5018 if (PetscDefined(USE_DEBUG)) { 5019 PetscInt nv, row, col, ndiag; 5020 5021 PetscCall(VecGetLocalSize(v, &nv)); 5022 PetscCall(MatGetLocalSize(mat, &row, &col)); 5023 ndiag = PetscMin(row, col); 5024 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); 5025 } 5026 5027 PetscUseTypeMethod(mat, getdiagonal, v); 5028 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5029 PetscFunctionReturn(PETSC_SUCCESS); 5030 } 5031 5032 /*@ 5033 MatGetRowMin - Gets the minimum value (of the real part) of each 5034 row of the matrix 5035 5036 Logically Collective 5037 5038 Input Parameter: 5039 . mat - the matrix 5040 5041 Output Parameters: 5042 + v - the vector for storing the maximums 5043 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5044 5045 Level: intermediate 5046 5047 Note: 5048 The result of this call are the same as if one converted the matrix to dense format 5049 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5050 5051 This code is only implemented for a couple of matrix formats. 5052 5053 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5054 `MatGetRowMax()` 5055 @*/ 5056 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5057 { 5058 PetscFunctionBegin; 5059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5060 PetscValidType(mat, 1); 5061 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5062 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5063 5064 if (!mat->cmap->N) { 5065 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5066 if (idx) { 5067 PetscInt i, m = mat->rmap->n; 5068 for (i = 0; i < m; i++) idx[i] = -1; 5069 } 5070 } else { 5071 MatCheckPreallocated(mat, 1); 5072 } 5073 PetscUseTypeMethod(mat, getrowmin, v, idx); 5074 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5075 PetscFunctionReturn(PETSC_SUCCESS); 5076 } 5077 5078 /*@ 5079 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5080 row of the matrix 5081 5082 Logically Collective 5083 5084 Input Parameter: 5085 . mat - the matrix 5086 5087 Output Parameters: 5088 + v - the vector for storing the minimums 5089 - idx - the indices of the column found for each row (or `NULL` if not needed) 5090 5091 Level: intermediate 5092 5093 Notes: 5094 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5095 row is 0 (the first column). 5096 5097 This code is only implemented for a couple of matrix formats. 5098 5099 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5100 @*/ 5101 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5102 { 5103 PetscFunctionBegin; 5104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5105 PetscValidType(mat, 1); 5106 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5107 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5108 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5109 5110 if (!mat->cmap->N) { 5111 PetscCall(VecSet(v, 0.0)); 5112 if (idx) { 5113 PetscInt i, m = mat->rmap->n; 5114 for (i = 0; i < m; i++) idx[i] = -1; 5115 } 5116 } else { 5117 MatCheckPreallocated(mat, 1); 5118 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5119 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5120 } 5121 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5122 PetscFunctionReturn(PETSC_SUCCESS); 5123 } 5124 5125 /*@ 5126 MatGetRowMax - Gets the maximum value (of the real part) of each 5127 row of the matrix 5128 5129 Logically Collective 5130 5131 Input Parameter: 5132 . mat - the matrix 5133 5134 Output Parameters: 5135 + v - the vector for storing the maximums 5136 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5137 5138 Level: intermediate 5139 5140 Notes: 5141 The result of this call are the same as if one converted the matrix to dense format 5142 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5143 5144 This code is only implemented for a couple of matrix formats. 5145 5146 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5147 @*/ 5148 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5149 { 5150 PetscFunctionBegin; 5151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5152 PetscValidType(mat, 1); 5153 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5154 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5155 5156 if (!mat->cmap->N) { 5157 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5158 if (idx) { 5159 PetscInt i, m = mat->rmap->n; 5160 for (i = 0; i < m; i++) idx[i] = -1; 5161 } 5162 } else { 5163 MatCheckPreallocated(mat, 1); 5164 PetscUseTypeMethod(mat, getrowmax, v, idx); 5165 } 5166 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5167 PetscFunctionReturn(PETSC_SUCCESS); 5168 } 5169 5170 /*@ 5171 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5172 row of the matrix 5173 5174 Logically Collective 5175 5176 Input Parameter: 5177 . mat - the matrix 5178 5179 Output Parameters: 5180 + v - the vector for storing the maximums 5181 - idx - the indices of the column found for each row (or `NULL` if not needed) 5182 5183 Level: intermediate 5184 5185 Notes: 5186 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5187 row is 0 (the first column). 5188 5189 This code is only implemented for a couple of matrix formats. 5190 5191 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5192 @*/ 5193 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5194 { 5195 PetscFunctionBegin; 5196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5197 PetscValidType(mat, 1); 5198 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5199 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5200 5201 if (!mat->cmap->N) { 5202 PetscCall(VecSet(v, 0.0)); 5203 if (idx) { 5204 PetscInt i, m = mat->rmap->n; 5205 for (i = 0; i < m; i++) idx[i] = -1; 5206 } 5207 } else { 5208 MatCheckPreallocated(mat, 1); 5209 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5210 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5211 } 5212 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5213 PetscFunctionReturn(PETSC_SUCCESS); 5214 } 5215 5216 /*@ 5217 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5218 5219 Logically Collective 5220 5221 Input Parameter: 5222 . mat - the matrix 5223 5224 Output Parameter: 5225 . v - the vector for storing the sum 5226 5227 Level: intermediate 5228 5229 This code is only implemented for a couple of matrix formats. 5230 5231 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5232 @*/ 5233 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5234 { 5235 PetscFunctionBegin; 5236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5237 PetscValidType(mat, 1); 5238 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5240 5241 if (!mat->cmap->N) { 5242 PetscCall(VecSet(v, 0.0)); 5243 } else { 5244 MatCheckPreallocated(mat, 1); 5245 PetscUseTypeMethod(mat, getrowsumabs, v); 5246 } 5247 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5248 PetscFunctionReturn(PETSC_SUCCESS); 5249 } 5250 5251 /*@ 5252 MatGetRowSum - Gets the sum of each row of the matrix 5253 5254 Logically or Neighborhood Collective 5255 5256 Input Parameter: 5257 . mat - the matrix 5258 5259 Output Parameter: 5260 . v - the vector for storing the sum of rows 5261 5262 Level: intermediate 5263 5264 Note: 5265 This code is slow since it is not currently specialized for different formats 5266 5267 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5268 @*/ 5269 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5270 { 5271 Vec ones; 5272 5273 PetscFunctionBegin; 5274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5275 PetscValidType(mat, 1); 5276 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5277 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5278 MatCheckPreallocated(mat, 1); 5279 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5280 PetscCall(VecSet(ones, 1.)); 5281 PetscCall(MatMult(mat, ones, v)); 5282 PetscCall(VecDestroy(&ones)); 5283 PetscFunctionReturn(PETSC_SUCCESS); 5284 } 5285 5286 /*@ 5287 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5288 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5289 5290 Collective 5291 5292 Input Parameter: 5293 . mat - the matrix to provide the transpose 5294 5295 Output Parameter: 5296 . 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 5297 5298 Level: advanced 5299 5300 Note: 5301 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 5302 routine allows bypassing that call. 5303 5304 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5305 @*/ 5306 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5307 { 5308 MatParentState *rb = NULL; 5309 5310 PetscFunctionBegin; 5311 PetscCall(PetscNew(&rb)); 5312 rb->id = ((PetscObject)mat)->id; 5313 rb->state = 0; 5314 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5315 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscContainerUserDestroyDefault)); 5316 PetscFunctionReturn(PETSC_SUCCESS); 5317 } 5318 5319 /*@ 5320 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5321 5322 Collective 5323 5324 Input Parameters: 5325 + mat - the matrix to transpose 5326 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5327 5328 Output Parameter: 5329 . B - the transpose of the matrix 5330 5331 Level: intermediate 5332 5333 Notes: 5334 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5335 5336 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the 5337 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5338 5339 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. 5340 5341 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5342 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5343 5344 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5345 5346 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5347 5348 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5349 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5350 @*/ 5351 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5352 { 5353 PetscContainer rB = NULL; 5354 MatParentState *rb = NULL; 5355 5356 PetscFunctionBegin; 5357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5358 PetscValidType(mat, 1); 5359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5361 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5362 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5363 MatCheckPreallocated(mat, 1); 5364 if (reuse == MAT_REUSE_MATRIX) { 5365 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5366 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5367 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5368 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5369 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5370 } 5371 5372 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5373 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5374 PetscUseTypeMethod(mat, transpose, reuse, B); 5375 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5376 } 5377 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5378 5379 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5380 if (reuse != MAT_INPLACE_MATRIX) { 5381 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5382 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5383 rb->state = ((PetscObject)mat)->state; 5384 rb->nonzerostate = mat->nonzerostate; 5385 } 5386 PetscFunctionReturn(PETSC_SUCCESS); 5387 } 5388 5389 /*@ 5390 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5391 5392 Collective 5393 5394 Input Parameter: 5395 . A - the matrix to transpose 5396 5397 Output Parameter: 5398 . 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 5399 numerical portion. 5400 5401 Level: intermediate 5402 5403 Note: 5404 This is not supported for many matrix types, use `MatTranspose()` in those cases 5405 5406 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5407 @*/ 5408 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5409 { 5410 PetscFunctionBegin; 5411 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5412 PetscValidType(A, 1); 5413 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5414 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5415 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5416 PetscUseTypeMethod(A, transposesymbolic, B); 5417 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5418 5419 PetscCall(MatTransposeSetPrecursor(A, *B)); 5420 PetscFunctionReturn(PETSC_SUCCESS); 5421 } 5422 5423 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5424 { 5425 PetscContainer rB; 5426 MatParentState *rb; 5427 5428 PetscFunctionBegin; 5429 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5430 PetscValidType(A, 1); 5431 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5432 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5433 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5434 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5435 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5436 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5437 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5438 PetscFunctionReturn(PETSC_SUCCESS); 5439 } 5440 5441 /*@ 5442 MatIsTranspose - Test whether a matrix is another one's transpose, 5443 or its own, in which case it tests symmetry. 5444 5445 Collective 5446 5447 Input Parameters: 5448 + A - the matrix to test 5449 . B - the matrix to test against, this can equal the first parameter 5450 - tol - tolerance, differences between entries smaller than this are counted as zero 5451 5452 Output Parameter: 5453 . flg - the result 5454 5455 Level: intermediate 5456 5457 Notes: 5458 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5459 test involves parallel copies of the block off-diagonal parts of the matrix. 5460 5461 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5462 @*/ 5463 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5464 { 5465 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5466 5467 PetscFunctionBegin; 5468 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5469 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5470 PetscAssertPointer(flg, 4); 5471 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5472 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5473 *flg = PETSC_FALSE; 5474 if (f && g) { 5475 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5476 PetscCall((*f)(A, B, tol, flg)); 5477 } else { 5478 MatType mattype; 5479 5480 PetscCall(MatGetType(f ? B : A, &mattype)); 5481 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5482 } 5483 PetscFunctionReturn(PETSC_SUCCESS); 5484 } 5485 5486 /*@ 5487 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5488 5489 Collective 5490 5491 Input Parameters: 5492 + mat - the matrix to transpose and complex conjugate 5493 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5494 5495 Output Parameter: 5496 . B - the Hermitian transpose 5497 5498 Level: intermediate 5499 5500 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5501 @*/ 5502 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5503 { 5504 PetscFunctionBegin; 5505 PetscCall(MatTranspose(mat, reuse, B)); 5506 #if defined(PETSC_USE_COMPLEX) 5507 PetscCall(MatConjugate(*B)); 5508 #endif 5509 PetscFunctionReturn(PETSC_SUCCESS); 5510 } 5511 5512 /*@ 5513 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5514 5515 Collective 5516 5517 Input Parameters: 5518 + A - the matrix to test 5519 . B - the matrix to test against, this can equal the first parameter 5520 - tol - tolerance, differences between entries smaller than this are counted as zero 5521 5522 Output Parameter: 5523 . flg - the result 5524 5525 Level: intermediate 5526 5527 Notes: 5528 Only available for `MATAIJ` matrices. 5529 5530 The sequential algorithm 5531 has a running time of the order of the number of nonzeros; the parallel 5532 test involves parallel copies of the block off-diagonal parts of the matrix. 5533 5534 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5535 @*/ 5536 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5537 { 5538 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5539 5540 PetscFunctionBegin; 5541 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5542 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5543 PetscAssertPointer(flg, 4); 5544 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5545 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5546 if (f && g) { 5547 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5548 PetscCall((*f)(A, B, tol, flg)); 5549 } 5550 PetscFunctionReturn(PETSC_SUCCESS); 5551 } 5552 5553 /*@ 5554 MatPermute - Creates a new matrix with rows and columns permuted from the 5555 original. 5556 5557 Collective 5558 5559 Input Parameters: 5560 + mat - the matrix to permute 5561 . row - row permutation, each processor supplies only the permutation for its rows 5562 - col - column permutation, each processor supplies only the permutation for its columns 5563 5564 Output Parameter: 5565 . B - the permuted matrix 5566 5567 Level: advanced 5568 5569 Note: 5570 The index sets map from row/col of permuted matrix to row/col of original matrix. 5571 The index sets should be on the same communicator as mat and have the same local sizes. 5572 5573 Developer Note: 5574 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5575 exploit the fact that row and col are permutations, consider implementing the 5576 more general `MatCreateSubMatrix()` instead. 5577 5578 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5579 @*/ 5580 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5581 { 5582 PetscFunctionBegin; 5583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5584 PetscValidType(mat, 1); 5585 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5586 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5587 PetscAssertPointer(B, 4); 5588 PetscCheckSameComm(mat, 1, row, 2); 5589 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5592 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5593 MatCheckPreallocated(mat, 1); 5594 5595 if (mat->ops->permute) { 5596 PetscUseTypeMethod(mat, permute, row, col, B); 5597 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5598 } else { 5599 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5600 } 5601 PetscFunctionReturn(PETSC_SUCCESS); 5602 } 5603 5604 /*@ 5605 MatEqual - Compares two matrices. 5606 5607 Collective 5608 5609 Input Parameters: 5610 + A - the first matrix 5611 - B - the second matrix 5612 5613 Output Parameter: 5614 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5615 5616 Level: intermediate 5617 5618 Note: 5619 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product 5620 using several randomly created vectors, see `MatMultEqual()`. 5621 5622 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5623 @*/ 5624 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5625 { 5626 PetscFunctionBegin; 5627 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5628 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5629 PetscValidType(A, 1); 5630 PetscValidType(B, 2); 5631 PetscAssertPointer(flg, 3); 5632 PetscCheckSameComm(A, 1, B, 2); 5633 MatCheckPreallocated(A, 1); 5634 MatCheckPreallocated(B, 2); 5635 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5636 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5637 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, 5638 B->cmap->N); 5639 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5640 PetscUseTypeMethod(A, equal, B, flg); 5641 } else { 5642 PetscCall(MatMultEqual(A, B, 10, flg)); 5643 } 5644 PetscFunctionReturn(PETSC_SUCCESS); 5645 } 5646 5647 /*@ 5648 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5649 matrices that are stored as vectors. Either of the two scaling 5650 matrices can be `NULL`. 5651 5652 Collective 5653 5654 Input Parameters: 5655 + mat - the matrix to be scaled 5656 . l - the left scaling vector (or `NULL`) 5657 - r - the right scaling vector (or `NULL`) 5658 5659 Level: intermediate 5660 5661 Note: 5662 `MatDiagonalScale()` computes $A = LAR$, where 5663 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5664 The L scales the rows of the matrix, the R scales the columns of the matrix. 5665 5666 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5667 @*/ 5668 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5669 { 5670 PetscFunctionBegin; 5671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5672 PetscValidType(mat, 1); 5673 if (l) { 5674 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5675 PetscCheckSameComm(mat, 1, l, 2); 5676 } 5677 if (r) { 5678 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5679 PetscCheckSameComm(mat, 1, r, 3); 5680 } 5681 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5682 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5683 MatCheckPreallocated(mat, 1); 5684 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5685 5686 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5687 PetscUseTypeMethod(mat, diagonalscale, l, r); 5688 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5689 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5690 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5691 PetscFunctionReturn(PETSC_SUCCESS); 5692 } 5693 5694 /*@ 5695 MatScale - Scales all elements of a matrix by a given number. 5696 5697 Logically Collective 5698 5699 Input Parameters: 5700 + mat - the matrix to be scaled 5701 - a - the scaling value 5702 5703 Level: intermediate 5704 5705 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5706 @*/ 5707 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5708 { 5709 PetscFunctionBegin; 5710 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5711 PetscValidType(mat, 1); 5712 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5713 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5714 PetscValidLogicalCollectiveScalar(mat, a, 2); 5715 MatCheckPreallocated(mat, 1); 5716 5717 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5718 if (a != (PetscScalar)1.0) { 5719 PetscUseTypeMethod(mat, scale, a); 5720 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5721 } 5722 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5723 PetscFunctionReturn(PETSC_SUCCESS); 5724 } 5725 5726 /*@ 5727 MatNorm - Calculates various norms of a matrix. 5728 5729 Collective 5730 5731 Input Parameters: 5732 + mat - the matrix 5733 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5734 5735 Output Parameter: 5736 . nrm - the resulting norm 5737 5738 Level: intermediate 5739 5740 .seealso: [](ch_matrices), `Mat` 5741 @*/ 5742 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5743 { 5744 PetscFunctionBegin; 5745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5746 PetscValidType(mat, 1); 5747 PetscAssertPointer(nrm, 3); 5748 5749 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5750 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5751 MatCheckPreallocated(mat, 1); 5752 5753 PetscUseTypeMethod(mat, norm, type, nrm); 5754 PetscFunctionReturn(PETSC_SUCCESS); 5755 } 5756 5757 /* 5758 This variable is used to prevent counting of MatAssemblyBegin() that 5759 are called from within a MatAssemblyEnd(). 5760 */ 5761 static PetscInt MatAssemblyEnd_InUse = 0; 5762 /*@ 5763 MatAssemblyBegin - Begins assembling the matrix. This routine should 5764 be called after completing all calls to `MatSetValues()`. 5765 5766 Collective 5767 5768 Input Parameters: 5769 + mat - the matrix 5770 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5771 5772 Level: beginner 5773 5774 Notes: 5775 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5776 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5777 5778 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5779 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5780 using the matrix. 5781 5782 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5783 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 5784 a global collective operation requiring all processes that share the matrix. 5785 5786 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5787 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5788 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5789 5790 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5791 @*/ 5792 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5793 { 5794 PetscFunctionBegin; 5795 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5796 PetscValidType(mat, 1); 5797 MatCheckPreallocated(mat, 1); 5798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5799 if (mat->assembled) { 5800 mat->was_assembled = PETSC_TRUE; 5801 mat->assembled = PETSC_FALSE; 5802 } 5803 5804 if (!MatAssemblyEnd_InUse) { 5805 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5806 PetscTryTypeMethod(mat, assemblybegin, type); 5807 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5808 } else PetscTryTypeMethod(mat, assemblybegin, type); 5809 PetscFunctionReturn(PETSC_SUCCESS); 5810 } 5811 5812 /*@ 5813 MatAssembled - Indicates if a matrix has been assembled and is ready for 5814 use; for example, in matrix-vector product. 5815 5816 Not Collective 5817 5818 Input Parameter: 5819 . mat - the matrix 5820 5821 Output Parameter: 5822 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5823 5824 Level: advanced 5825 5826 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5827 @*/ 5828 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5829 { 5830 PetscFunctionBegin; 5831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5832 PetscAssertPointer(assembled, 2); 5833 *assembled = mat->assembled; 5834 PetscFunctionReturn(PETSC_SUCCESS); 5835 } 5836 5837 /*@ 5838 MatAssemblyEnd - Completes assembling the matrix. This routine should 5839 be called after `MatAssemblyBegin()`. 5840 5841 Collective 5842 5843 Input Parameters: 5844 + mat - the matrix 5845 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5846 5847 Options Database Keys: 5848 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5849 . -mat_view ::ascii_info_detail - Prints more detailed info 5850 . -mat_view - Prints matrix in ASCII format 5851 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5852 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5853 . -display <name> - Sets display name (default is host) 5854 . -draw_pause <sec> - Sets number of seconds to pause after display 5855 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5856 . -viewer_socket_machine <machine> - Machine to use for socket 5857 . -viewer_socket_port <port> - Port number to use for socket 5858 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5859 5860 Level: beginner 5861 5862 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5863 @*/ 5864 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5865 { 5866 static PetscInt inassm = 0; 5867 PetscBool flg = PETSC_FALSE; 5868 5869 PetscFunctionBegin; 5870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5871 PetscValidType(mat, 1); 5872 5873 inassm++; 5874 MatAssemblyEnd_InUse++; 5875 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5876 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5877 PetscTryTypeMethod(mat, assemblyend, type); 5878 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5879 } else PetscTryTypeMethod(mat, assemblyend, type); 5880 5881 /* Flush assembly is not a true assembly */ 5882 if (type != MAT_FLUSH_ASSEMBLY) { 5883 if (mat->num_ass) { 5884 if (!mat->symmetry_eternal) { 5885 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5886 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5887 } 5888 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5889 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5890 } 5891 mat->num_ass++; 5892 mat->assembled = PETSC_TRUE; 5893 mat->ass_nonzerostate = mat->nonzerostate; 5894 } 5895 5896 mat->insertmode = NOT_SET_VALUES; 5897 MatAssemblyEnd_InUse--; 5898 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5899 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5900 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5901 5902 if (mat->checksymmetryonassembly) { 5903 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5904 if (flg) { 5905 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5906 } else { 5907 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5908 } 5909 } 5910 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5911 } 5912 inassm--; 5913 PetscFunctionReturn(PETSC_SUCCESS); 5914 } 5915 5916 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5917 /*@ 5918 MatSetOption - Sets a parameter option for a matrix. Some options 5919 may be specific to certain storage formats. Some options 5920 determine how values will be inserted (or added). Sorted, 5921 row-oriented input will generally assemble the fastest. The default 5922 is row-oriented. 5923 5924 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5925 5926 Input Parameters: 5927 + mat - the matrix 5928 . op - the option, one of those listed below (and possibly others), 5929 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5930 5931 Options Describing Matrix Structure: 5932 + `MAT_SPD` - symmetric positive definite 5933 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5934 . `MAT_HERMITIAN` - transpose is the complex conjugation 5935 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5936 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5937 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5938 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5939 5940 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5941 do not need to be computed (usually at a high cost) 5942 5943 Options For Use with `MatSetValues()`: 5944 Insert a logically dense subblock, which can be 5945 . `MAT_ROW_ORIENTED` - row-oriented (default) 5946 5947 These options reflect the data you pass in with `MatSetValues()`; it has 5948 nothing to do with how the data is stored internally in the matrix 5949 data structure. 5950 5951 When (re)assembling a matrix, we can restrict the input for 5952 efficiency/debugging purposes. These options include 5953 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5954 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5955 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5956 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5957 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5958 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5959 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5960 performance for very large process counts. 5961 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5962 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5963 functions, instead sending only neighbor messages. 5964 5965 Level: intermediate 5966 5967 Notes: 5968 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5969 5970 Some options are relevant only for particular matrix types and 5971 are thus ignored by others. Other options are not supported by 5972 certain matrix types and will generate an error message if set. 5973 5974 If using Fortran to compute a matrix, one may need to 5975 use the column-oriented option (or convert to the row-oriented 5976 format). 5977 5978 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5979 that would generate a new entry in the nonzero structure is instead 5980 ignored. Thus, if memory has not already been allocated for this particular 5981 data, then the insertion is ignored. For dense matrices, in which 5982 the entire array is allocated, no entries are ever ignored. 5983 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5984 5985 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5986 that would generate a new entry in the nonzero structure instead produces 5987 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 5988 5989 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5990 that would generate a new entry that has not been preallocated will 5991 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5992 only.) This is a useful flag when debugging matrix memory preallocation. 5993 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5994 5995 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5996 other processors should be dropped, rather than stashed. 5997 This is useful if you know that the "owning" processor is also 5998 always generating the correct matrix entries, so that PETSc need 5999 not transfer duplicate entries generated on another processor. 6000 6001 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6002 searches during matrix assembly. When this flag is set, the hash table 6003 is created during the first matrix assembly. This hash table is 6004 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6005 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6006 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6007 supported by `MATMPIBAIJ` format only. 6008 6009 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6010 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6011 6012 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6013 a zero location in the matrix 6014 6015 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6016 6017 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6018 zero row routines and thus improves performance for very large process counts. 6019 6020 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6021 part of the matrix (since they should match the upper triangular part). 6022 6023 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6024 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6025 with finite difference schemes with non-periodic boundary conditions. 6026 6027 Developer Note: 6028 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6029 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6030 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6031 not changed. 6032 6033 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6034 @*/ 6035 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6036 { 6037 PetscFunctionBegin; 6038 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6039 if (op > 0) { 6040 PetscValidLogicalCollectiveEnum(mat, op, 2); 6041 PetscValidLogicalCollectiveBool(mat, flg, 3); 6042 } 6043 6044 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); 6045 6046 switch (op) { 6047 case MAT_FORCE_DIAGONAL_ENTRIES: 6048 mat->force_diagonals = flg; 6049 PetscFunctionReturn(PETSC_SUCCESS); 6050 case MAT_NO_OFF_PROC_ENTRIES: 6051 mat->nooffprocentries = flg; 6052 PetscFunctionReturn(PETSC_SUCCESS); 6053 case MAT_SUBSET_OFF_PROC_ENTRIES: 6054 mat->assembly_subset = flg; 6055 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6056 #if !defined(PETSC_HAVE_MPIUNI) 6057 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6058 #endif 6059 mat->stash.first_assembly_done = PETSC_FALSE; 6060 } 6061 PetscFunctionReturn(PETSC_SUCCESS); 6062 case MAT_NO_OFF_PROC_ZERO_ROWS: 6063 mat->nooffproczerorows = flg; 6064 PetscFunctionReturn(PETSC_SUCCESS); 6065 case MAT_SPD: 6066 if (flg) { 6067 mat->spd = PETSC_BOOL3_TRUE; 6068 mat->symmetric = PETSC_BOOL3_TRUE; 6069 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6070 } else { 6071 mat->spd = PETSC_BOOL3_FALSE; 6072 } 6073 break; 6074 case MAT_SYMMETRIC: 6075 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6076 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6077 #if !defined(PETSC_USE_COMPLEX) 6078 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6079 #endif 6080 break; 6081 case MAT_HERMITIAN: 6082 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6083 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6084 #if !defined(PETSC_USE_COMPLEX) 6085 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6086 #endif 6087 break; 6088 case MAT_STRUCTURALLY_SYMMETRIC: 6089 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6090 break; 6091 case MAT_SYMMETRY_ETERNAL: 6092 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"); 6093 mat->symmetry_eternal = flg; 6094 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6095 break; 6096 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6097 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"); 6098 mat->structural_symmetry_eternal = flg; 6099 break; 6100 case MAT_SPD_ETERNAL: 6101 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"); 6102 mat->spd_eternal = flg; 6103 if (flg) { 6104 mat->structural_symmetry_eternal = PETSC_TRUE; 6105 mat->symmetry_eternal = PETSC_TRUE; 6106 } 6107 break; 6108 case MAT_STRUCTURE_ONLY: 6109 mat->structure_only = flg; 6110 break; 6111 case MAT_SORTED_FULL: 6112 mat->sortedfull = flg; 6113 break; 6114 default: 6115 break; 6116 } 6117 PetscTryTypeMethod(mat, setoption, op, flg); 6118 PetscFunctionReturn(PETSC_SUCCESS); 6119 } 6120 6121 /*@ 6122 MatGetOption - Gets a parameter option that has been set for a matrix. 6123 6124 Logically Collective 6125 6126 Input Parameters: 6127 + mat - the matrix 6128 - op - the option, this only responds to certain options, check the code for which ones 6129 6130 Output Parameter: 6131 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6132 6133 Level: intermediate 6134 6135 Notes: 6136 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6137 6138 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6139 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6140 6141 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6142 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6143 @*/ 6144 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6145 { 6146 PetscFunctionBegin; 6147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6148 PetscValidType(mat, 1); 6149 6150 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); 6151 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()"); 6152 6153 switch (op) { 6154 case MAT_NO_OFF_PROC_ENTRIES: 6155 *flg = mat->nooffprocentries; 6156 break; 6157 case MAT_NO_OFF_PROC_ZERO_ROWS: 6158 *flg = mat->nooffproczerorows; 6159 break; 6160 case MAT_SYMMETRIC: 6161 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6162 break; 6163 case MAT_HERMITIAN: 6164 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6165 break; 6166 case MAT_STRUCTURALLY_SYMMETRIC: 6167 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6168 break; 6169 case MAT_SPD: 6170 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6171 break; 6172 case MAT_SYMMETRY_ETERNAL: 6173 *flg = mat->symmetry_eternal; 6174 break; 6175 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6176 *flg = mat->symmetry_eternal; 6177 break; 6178 default: 6179 break; 6180 } 6181 PetscFunctionReturn(PETSC_SUCCESS); 6182 } 6183 6184 /*@ 6185 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6186 this routine retains the old nonzero structure. 6187 6188 Logically Collective 6189 6190 Input Parameter: 6191 . mat - the matrix 6192 6193 Level: intermediate 6194 6195 Note: 6196 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. 6197 See the Performance chapter of the users manual for information on preallocating matrices. 6198 6199 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6200 @*/ 6201 PetscErrorCode MatZeroEntries(Mat mat) 6202 { 6203 PetscFunctionBegin; 6204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6205 PetscValidType(mat, 1); 6206 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6207 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"); 6208 MatCheckPreallocated(mat, 1); 6209 6210 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6211 PetscUseTypeMethod(mat, zeroentries); 6212 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6214 PetscFunctionReturn(PETSC_SUCCESS); 6215 } 6216 6217 /*@ 6218 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6219 of a set of rows and columns of a matrix. 6220 6221 Collective 6222 6223 Input Parameters: 6224 + mat - the matrix 6225 . numRows - the number of rows/columns to zero 6226 . rows - the global row indices 6227 . diag - value put in the diagonal of the eliminated rows 6228 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6229 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6230 6231 Level: intermediate 6232 6233 Notes: 6234 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6235 6236 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6237 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 6238 6239 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6240 Krylov method to take advantage of the known solution on the zeroed rows. 6241 6242 For the parallel case, all processes that share the matrix (i.e., 6243 those in the communicator used for matrix creation) MUST call this 6244 routine, regardless of whether any rows being zeroed are owned by 6245 them. 6246 6247 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6248 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 6249 missing. 6250 6251 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6252 list only rows local to itself). 6253 6254 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6255 6256 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6257 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6258 @*/ 6259 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6260 { 6261 PetscFunctionBegin; 6262 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6263 PetscValidType(mat, 1); 6264 if (numRows) PetscAssertPointer(rows, 3); 6265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6266 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6267 MatCheckPreallocated(mat, 1); 6268 6269 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6270 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6271 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6272 PetscFunctionReturn(PETSC_SUCCESS); 6273 } 6274 6275 /*@ 6276 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6277 of a set of rows and columns of a matrix. 6278 6279 Collective 6280 6281 Input Parameters: 6282 + mat - the matrix 6283 . is - the rows to zero 6284 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6285 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6286 - b - optional vector of right-hand side, that will be adjusted by provided solution 6287 6288 Level: intermediate 6289 6290 Note: 6291 See `MatZeroRowsColumns()` for details on how this routine operates. 6292 6293 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6294 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6295 @*/ 6296 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6297 { 6298 PetscInt numRows; 6299 const PetscInt *rows; 6300 6301 PetscFunctionBegin; 6302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6303 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6304 PetscValidType(mat, 1); 6305 PetscValidType(is, 2); 6306 PetscCall(ISGetLocalSize(is, &numRows)); 6307 PetscCall(ISGetIndices(is, &rows)); 6308 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6309 PetscCall(ISRestoreIndices(is, &rows)); 6310 PetscFunctionReturn(PETSC_SUCCESS); 6311 } 6312 6313 /*@ 6314 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6315 of a set of rows of a matrix. 6316 6317 Collective 6318 6319 Input Parameters: 6320 + mat - the matrix 6321 . numRows - the number of rows to zero 6322 . rows - the global row indices 6323 . diag - value put in the diagonal of the zeroed rows 6324 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6325 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6326 6327 Level: intermediate 6328 6329 Notes: 6330 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6331 6332 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6333 6334 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6335 Krylov method to take advantage of the known solution on the zeroed rows. 6336 6337 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) 6338 from the matrix. 6339 6340 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6341 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6342 formats this does not alter the nonzero structure. 6343 6344 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6345 of the matrix is not changed the values are 6346 merely zeroed. 6347 6348 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6349 formats can optionally remove the main diagonal entry from the 6350 nonzero structure as well, by passing 0.0 as the final argument). 6351 6352 For the parallel case, all processes that share the matrix (i.e., 6353 those in the communicator used for matrix creation) MUST call this 6354 routine, regardless of whether any rows being zeroed are owned by 6355 them. 6356 6357 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6358 list only rows local to itself). 6359 6360 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6361 owns that are to be zeroed. This saves a global synchronization in the implementation. 6362 6363 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6364 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6365 @*/ 6366 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6367 { 6368 PetscFunctionBegin; 6369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6370 PetscValidType(mat, 1); 6371 if (numRows) PetscAssertPointer(rows, 3); 6372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6373 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6374 MatCheckPreallocated(mat, 1); 6375 6376 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6377 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6378 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6379 PetscFunctionReturn(PETSC_SUCCESS); 6380 } 6381 6382 /*@ 6383 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6384 of a set of rows of a matrix indicated by an `IS` 6385 6386 Collective 6387 6388 Input Parameters: 6389 + mat - the matrix 6390 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6391 . diag - value put in all diagonals of eliminated rows 6392 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6393 - b - optional vector of right-hand side, that will be adjusted by provided solution 6394 6395 Level: intermediate 6396 6397 Note: 6398 See `MatZeroRows()` for details on how this routine operates. 6399 6400 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6401 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6402 @*/ 6403 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6404 { 6405 PetscInt numRows = 0; 6406 const PetscInt *rows = NULL; 6407 6408 PetscFunctionBegin; 6409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6410 PetscValidType(mat, 1); 6411 if (is) { 6412 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6413 PetscCall(ISGetLocalSize(is, &numRows)); 6414 PetscCall(ISGetIndices(is, &rows)); 6415 } 6416 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6417 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6418 PetscFunctionReturn(PETSC_SUCCESS); 6419 } 6420 6421 /*@ 6422 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6423 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6424 6425 Collective 6426 6427 Input Parameters: 6428 + mat - the matrix 6429 . numRows - the number of rows to remove 6430 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6431 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6432 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6433 - b - optional vector of right-hand side, that will be adjusted by provided solution 6434 6435 Level: intermediate 6436 6437 Notes: 6438 See `MatZeroRows()` for details on how this routine operates. 6439 6440 The grid coordinates are across the entire grid, not just the local portion 6441 6442 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6443 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6444 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6445 `DM_BOUNDARY_PERIODIC` boundary type. 6446 6447 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 6448 a single value per point) you can skip filling those indices. 6449 6450 Fortran Note: 6451 `idxm` and `idxn` should be declared as 6452 $ MatStencil idxm(4, m) 6453 and the values inserted using 6454 .vb 6455 idxm(MatStencil_i, 1) = i 6456 idxm(MatStencil_j, 1) = j 6457 idxm(MatStencil_k, 1) = k 6458 idxm(MatStencil_c, 1) = c 6459 etc 6460 .ve 6461 6462 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6463 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6464 @*/ 6465 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6466 { 6467 PetscInt dim = mat->stencil.dim; 6468 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6469 PetscInt *dims = mat->stencil.dims + 1; 6470 PetscInt *starts = mat->stencil.starts; 6471 PetscInt *dxm = (PetscInt *)rows; 6472 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6473 6474 PetscFunctionBegin; 6475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6476 PetscValidType(mat, 1); 6477 if (numRows) PetscAssertPointer(rows, 3); 6478 6479 PetscCall(PetscMalloc1(numRows, &jdxm)); 6480 for (i = 0; i < numRows; ++i) { 6481 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6482 for (j = 0; j < 3 - sdim; ++j) dxm++; 6483 /* Local index in X dir */ 6484 tmp = *dxm++ - starts[0]; 6485 /* Loop over remaining dimensions */ 6486 for (j = 0; j < dim - 1; ++j) { 6487 /* If nonlocal, set index to be negative */ 6488 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6489 /* Update local index */ 6490 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6491 } 6492 /* Skip component slot if necessary */ 6493 if (mat->stencil.noc) dxm++; 6494 /* Local row number */ 6495 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6496 } 6497 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6498 PetscCall(PetscFree(jdxm)); 6499 PetscFunctionReturn(PETSC_SUCCESS); 6500 } 6501 6502 /*@ 6503 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6504 of a set of rows and columns of a matrix. 6505 6506 Collective 6507 6508 Input Parameters: 6509 + mat - the matrix 6510 . numRows - the number of rows/columns to remove 6511 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6512 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6513 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6514 - b - optional vector of right-hand side, that will be adjusted by provided solution 6515 6516 Level: intermediate 6517 6518 Notes: 6519 See `MatZeroRowsColumns()` for details on how this routine operates. 6520 6521 The grid coordinates are across the entire grid, not just the local portion 6522 6523 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6524 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6525 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6526 `DM_BOUNDARY_PERIODIC` boundary type. 6527 6528 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 6529 a single value per point) you can skip filling those indices. 6530 6531 Fortran Note: 6532 `idxm` and `idxn` should be declared as 6533 $ MatStencil idxm(4, m) 6534 and the values inserted using 6535 .vb 6536 idxm(MatStencil_i, 1) = i 6537 idxm(MatStencil_j, 1) = j 6538 idxm(MatStencil_k, 1) = k 6539 idxm(MatStencil_c, 1) = c 6540 etc 6541 .ve 6542 6543 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6544 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6545 @*/ 6546 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6547 { 6548 PetscInt dim = mat->stencil.dim; 6549 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6550 PetscInt *dims = mat->stencil.dims + 1; 6551 PetscInt *starts = mat->stencil.starts; 6552 PetscInt *dxm = (PetscInt *)rows; 6553 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6554 6555 PetscFunctionBegin; 6556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6557 PetscValidType(mat, 1); 6558 if (numRows) PetscAssertPointer(rows, 3); 6559 6560 PetscCall(PetscMalloc1(numRows, &jdxm)); 6561 for (i = 0; i < numRows; ++i) { 6562 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6563 for (j = 0; j < 3 - sdim; ++j) dxm++; 6564 /* Local index in X dir */ 6565 tmp = *dxm++ - starts[0]; 6566 /* Loop over remaining dimensions */ 6567 for (j = 0; j < dim - 1; ++j) { 6568 /* If nonlocal, set index to be negative */ 6569 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6570 /* Update local index */ 6571 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6572 } 6573 /* Skip component slot if necessary */ 6574 if (mat->stencil.noc) dxm++; 6575 /* Local row number */ 6576 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6577 } 6578 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6579 PetscCall(PetscFree(jdxm)); 6580 PetscFunctionReturn(PETSC_SUCCESS); 6581 } 6582 6583 /*@ 6584 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6585 of a set of rows of a matrix; using local numbering of rows. 6586 6587 Collective 6588 6589 Input Parameters: 6590 + mat - the matrix 6591 . numRows - the number of rows to remove 6592 . rows - the local row indices 6593 . diag - value put in all diagonals of eliminated rows 6594 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6595 - b - optional vector of right-hand side, that will be adjusted by provided solution 6596 6597 Level: intermediate 6598 6599 Notes: 6600 Before calling `MatZeroRowsLocal()`, the user must first set the 6601 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6602 6603 See `MatZeroRows()` for details on how this routine operates. 6604 6605 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6606 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6607 @*/ 6608 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6609 { 6610 PetscFunctionBegin; 6611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6612 PetscValidType(mat, 1); 6613 if (numRows) PetscAssertPointer(rows, 3); 6614 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6615 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6616 MatCheckPreallocated(mat, 1); 6617 6618 if (mat->ops->zerorowslocal) { 6619 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6620 } else { 6621 IS is, newis; 6622 const PetscInt *newRows; 6623 6624 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6625 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6626 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6627 PetscCall(ISGetIndices(newis, &newRows)); 6628 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6629 PetscCall(ISRestoreIndices(newis, &newRows)); 6630 PetscCall(ISDestroy(&newis)); 6631 PetscCall(ISDestroy(&is)); 6632 } 6633 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6634 PetscFunctionReturn(PETSC_SUCCESS); 6635 } 6636 6637 /*@ 6638 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6639 of a set of rows of a matrix; using local numbering of rows. 6640 6641 Collective 6642 6643 Input Parameters: 6644 + mat - the matrix 6645 . is - index set of rows to remove 6646 . diag - value put in all diagonals of eliminated rows 6647 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6648 - b - optional vector of right-hand side, that will be adjusted by provided solution 6649 6650 Level: intermediate 6651 6652 Notes: 6653 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6654 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6655 6656 See `MatZeroRows()` for details on how this routine operates. 6657 6658 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6659 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6660 @*/ 6661 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6662 { 6663 PetscInt numRows; 6664 const PetscInt *rows; 6665 6666 PetscFunctionBegin; 6667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6668 PetscValidType(mat, 1); 6669 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6670 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6671 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6672 MatCheckPreallocated(mat, 1); 6673 6674 PetscCall(ISGetLocalSize(is, &numRows)); 6675 PetscCall(ISGetIndices(is, &rows)); 6676 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6677 PetscCall(ISRestoreIndices(is, &rows)); 6678 PetscFunctionReturn(PETSC_SUCCESS); 6679 } 6680 6681 /*@ 6682 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6683 of a set of rows and columns of a matrix; using local numbering of rows. 6684 6685 Collective 6686 6687 Input Parameters: 6688 + mat - the matrix 6689 . numRows - the number of rows to remove 6690 . rows - the global row indices 6691 . diag - value put in all diagonals of eliminated rows 6692 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6693 - b - optional vector of right-hand side, that will be adjusted by provided solution 6694 6695 Level: intermediate 6696 6697 Notes: 6698 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6699 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6700 6701 See `MatZeroRowsColumns()` for details on how this routine operates. 6702 6703 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6704 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6705 @*/ 6706 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6707 { 6708 IS is, newis; 6709 const PetscInt *newRows; 6710 6711 PetscFunctionBegin; 6712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6713 PetscValidType(mat, 1); 6714 if (numRows) PetscAssertPointer(rows, 3); 6715 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6716 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6717 MatCheckPreallocated(mat, 1); 6718 6719 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6720 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6721 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6722 PetscCall(ISGetIndices(newis, &newRows)); 6723 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6724 PetscCall(ISRestoreIndices(newis, &newRows)); 6725 PetscCall(ISDestroy(&newis)); 6726 PetscCall(ISDestroy(&is)); 6727 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6728 PetscFunctionReturn(PETSC_SUCCESS); 6729 } 6730 6731 /*@ 6732 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6733 of a set of rows and columns of a matrix; using local numbering of rows. 6734 6735 Collective 6736 6737 Input Parameters: 6738 + mat - the matrix 6739 . is - index set of rows to remove 6740 . diag - value put in all diagonals of eliminated rows 6741 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6742 - b - optional vector of right-hand side, that will be adjusted by provided solution 6743 6744 Level: intermediate 6745 6746 Notes: 6747 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6748 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6749 6750 See `MatZeroRowsColumns()` for details on how this routine operates. 6751 6752 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6753 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6754 @*/ 6755 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6756 { 6757 PetscInt numRows; 6758 const PetscInt *rows; 6759 6760 PetscFunctionBegin; 6761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6762 PetscValidType(mat, 1); 6763 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6764 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6765 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6766 MatCheckPreallocated(mat, 1); 6767 6768 PetscCall(ISGetLocalSize(is, &numRows)); 6769 PetscCall(ISGetIndices(is, &rows)); 6770 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6771 PetscCall(ISRestoreIndices(is, &rows)); 6772 PetscFunctionReturn(PETSC_SUCCESS); 6773 } 6774 6775 /*@ 6776 MatGetSize - Returns the numbers of rows and columns in a matrix. 6777 6778 Not Collective 6779 6780 Input Parameter: 6781 . mat - the matrix 6782 6783 Output Parameters: 6784 + m - the number of global rows 6785 - n - the number of global columns 6786 6787 Level: beginner 6788 6789 Note: 6790 Both output parameters can be `NULL` on input. 6791 6792 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6793 @*/ 6794 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6795 { 6796 PetscFunctionBegin; 6797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6798 if (m) *m = mat->rmap->N; 6799 if (n) *n = mat->cmap->N; 6800 PetscFunctionReturn(PETSC_SUCCESS); 6801 } 6802 6803 /*@ 6804 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6805 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6806 6807 Not Collective 6808 6809 Input Parameter: 6810 . mat - the matrix 6811 6812 Output Parameters: 6813 + m - the number of local rows, use `NULL` to not obtain this value 6814 - n - the number of local columns, use `NULL` to not obtain this value 6815 6816 Level: beginner 6817 6818 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6819 @*/ 6820 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6821 { 6822 PetscFunctionBegin; 6823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6824 if (m) PetscAssertPointer(m, 2); 6825 if (n) PetscAssertPointer(n, 3); 6826 if (m) *m = mat->rmap->n; 6827 if (n) *n = mat->cmap->n; 6828 PetscFunctionReturn(PETSC_SUCCESS); 6829 } 6830 6831 /*@ 6832 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6833 vector one multiplies this matrix by that are owned by this processor. 6834 6835 Not Collective, unless matrix has not been allocated, then collective 6836 6837 Input Parameter: 6838 . mat - the matrix 6839 6840 Output Parameters: 6841 + m - the global index of the first local column, use `NULL` to not obtain this value 6842 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6843 6844 Level: developer 6845 6846 Notes: 6847 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6848 6849 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6850 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6851 6852 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6853 the local values in the matrix. 6854 6855 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6856 Layouts](sec_matlayout) for details on matrix layouts. 6857 6858 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6859 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6860 @*/ 6861 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6862 { 6863 PetscFunctionBegin; 6864 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6865 PetscValidType(mat, 1); 6866 if (m) PetscAssertPointer(m, 2); 6867 if (n) PetscAssertPointer(n, 3); 6868 MatCheckPreallocated(mat, 1); 6869 if (m) *m = mat->cmap->rstart; 6870 if (n) *n = mat->cmap->rend; 6871 PetscFunctionReturn(PETSC_SUCCESS); 6872 } 6873 6874 /*@ 6875 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6876 this MPI process. 6877 6878 Not Collective 6879 6880 Input Parameter: 6881 . mat - the matrix 6882 6883 Output Parameters: 6884 + m - the global index of the first local row, use `NULL` to not obtain this value 6885 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6886 6887 Level: beginner 6888 6889 Notes: 6890 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6891 6892 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6893 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6894 6895 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6896 the local values in the matrix. 6897 6898 The high argument is one more than the last element stored locally. 6899 6900 For all matrices it returns the range of matrix rows associated with rows of a vector that 6901 would contain the result of a matrix vector product with this matrix. See [Matrix 6902 Layouts](sec_matlayout) for details on matrix layouts. 6903 6904 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6905 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6906 @*/ 6907 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6908 { 6909 PetscFunctionBegin; 6910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6911 PetscValidType(mat, 1); 6912 if (m) PetscAssertPointer(m, 2); 6913 if (n) PetscAssertPointer(n, 3); 6914 MatCheckPreallocated(mat, 1); 6915 if (m) *m = mat->rmap->rstart; 6916 if (n) *n = mat->rmap->rend; 6917 PetscFunctionReturn(PETSC_SUCCESS); 6918 } 6919 6920 /*@C 6921 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6922 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6923 6924 Not Collective, unless matrix has not been allocated 6925 6926 Input Parameter: 6927 . mat - the matrix 6928 6929 Output Parameter: 6930 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6931 where `size` is the number of MPI processes used by `mat` 6932 6933 Level: beginner 6934 6935 Notes: 6936 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6937 6938 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6939 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6940 6941 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6942 the local values in the matrix. 6943 6944 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6945 would contain the result of a matrix vector product with this matrix. See [Matrix 6946 Layouts](sec_matlayout) for details on matrix layouts. 6947 6948 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6949 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6950 `DMDAGetGhostCorners()`, `DM` 6951 @*/ 6952 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6953 { 6954 PetscFunctionBegin; 6955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6956 PetscValidType(mat, 1); 6957 MatCheckPreallocated(mat, 1); 6958 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6959 PetscFunctionReturn(PETSC_SUCCESS); 6960 } 6961 6962 /*@C 6963 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6964 vector one multiplies this vector by that are owned by each processor. 6965 6966 Not Collective, unless matrix has not been allocated 6967 6968 Input Parameter: 6969 . mat - the matrix 6970 6971 Output Parameter: 6972 . ranges - start of each processors portion plus one more than the total length at the end 6973 6974 Level: beginner 6975 6976 Notes: 6977 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6978 6979 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6980 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6981 6982 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6983 the local values in the matrix. 6984 6985 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6986 Layouts](sec_matlayout) for details on matrix layouts. 6987 6988 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6989 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6990 `DMDAGetGhostCorners()`, `DM` 6991 @*/ 6992 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6993 { 6994 PetscFunctionBegin; 6995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6996 PetscValidType(mat, 1); 6997 MatCheckPreallocated(mat, 1); 6998 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6999 PetscFunctionReturn(PETSC_SUCCESS); 7000 } 7001 7002 /*@ 7003 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7004 7005 Not Collective 7006 7007 Input Parameter: 7008 . A - matrix 7009 7010 Output Parameters: 7011 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7012 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7013 7014 Level: intermediate 7015 7016 Note: 7017 You should call `ISDestroy()` on the returned `IS` 7018 7019 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7020 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7021 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7022 details on matrix layouts. 7023 7024 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7025 @*/ 7026 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7027 { 7028 PetscErrorCode (*f)(Mat, IS *, IS *); 7029 7030 PetscFunctionBegin; 7031 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7032 PetscValidType(A, 1); 7033 MatCheckPreallocated(A, 1); 7034 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7035 if (f) { 7036 PetscCall((*f)(A, rows, cols)); 7037 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7038 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7039 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7040 } 7041 PetscFunctionReturn(PETSC_SUCCESS); 7042 } 7043 7044 /*@ 7045 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7046 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7047 to complete the factorization. 7048 7049 Collective 7050 7051 Input Parameters: 7052 + fact - the factorized matrix obtained with `MatGetFactor()` 7053 . mat - the matrix 7054 . row - row permutation 7055 . col - column permutation 7056 - info - structure containing 7057 .vb 7058 levels - number of levels of fill. 7059 expected fill - as ratio of original fill. 7060 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7061 missing diagonal entries) 7062 .ve 7063 7064 Level: developer 7065 7066 Notes: 7067 See [Matrix Factorization](sec_matfactor) for additional information. 7068 7069 Most users should employ the `KSP` interface for linear solvers 7070 instead of working directly with matrix algebra routines such as this. 7071 See, e.g., `KSPCreate()`. 7072 7073 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7074 7075 Developer Note: 7076 The Fortran interface is not autogenerated as the 7077 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7078 7079 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7080 `MatGetOrdering()`, `MatFactorInfo` 7081 @*/ 7082 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7083 { 7084 PetscFunctionBegin; 7085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7086 PetscValidType(mat, 2); 7087 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7088 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7089 PetscAssertPointer(info, 5); 7090 PetscAssertPointer(fact, 1); 7091 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7092 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7093 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7094 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7095 MatCheckPreallocated(mat, 2); 7096 7097 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7098 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7099 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7100 PetscFunctionReturn(PETSC_SUCCESS); 7101 } 7102 7103 /*@ 7104 MatICCFactorSymbolic - Performs symbolic incomplete 7105 Cholesky factorization for a symmetric matrix. Use 7106 `MatCholeskyFactorNumeric()` to complete the factorization. 7107 7108 Collective 7109 7110 Input Parameters: 7111 + fact - the factorized matrix obtained with `MatGetFactor()` 7112 . mat - the matrix to be factored 7113 . perm - row and column permutation 7114 - info - structure containing 7115 .vb 7116 levels - number of levels of fill. 7117 expected fill - as ratio of original fill. 7118 .ve 7119 7120 Level: developer 7121 7122 Notes: 7123 Most users should employ the `KSP` interface for linear solvers 7124 instead of working directly with matrix algebra routines such as this. 7125 See, e.g., `KSPCreate()`. 7126 7127 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7128 7129 Developer Note: 7130 The Fortran interface is not autogenerated as the 7131 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7132 7133 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7134 @*/ 7135 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7136 { 7137 PetscFunctionBegin; 7138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7139 PetscValidType(mat, 2); 7140 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7141 PetscAssertPointer(info, 4); 7142 PetscAssertPointer(fact, 1); 7143 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7144 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7145 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7146 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7147 MatCheckPreallocated(mat, 2); 7148 7149 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7150 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7151 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7152 PetscFunctionReturn(PETSC_SUCCESS); 7153 } 7154 7155 /*@C 7156 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7157 points to an array of valid matrices, they may be reused to store the new 7158 submatrices. 7159 7160 Collective 7161 7162 Input Parameters: 7163 + mat - the matrix 7164 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7165 . irow - index set of rows to extract 7166 . icol - index set of columns to extract 7167 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7168 7169 Output Parameter: 7170 . submat - the array of submatrices 7171 7172 Level: advanced 7173 7174 Notes: 7175 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7176 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7177 to extract a parallel submatrix. 7178 7179 Some matrix types place restrictions on the row and column 7180 indices, such as that they be sorted or that they be equal to each other. 7181 7182 The index sets may not have duplicate entries. 7183 7184 When extracting submatrices from a parallel matrix, each processor can 7185 form a different submatrix by setting the rows and columns of its 7186 individual index sets according to the local submatrix desired. 7187 7188 When finished using the submatrices, the user should destroy 7189 them with `MatDestroySubMatrices()`. 7190 7191 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7192 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7193 7194 This routine creates the matrices in submat; you should NOT create them before 7195 calling it. It also allocates the array of matrix pointers submat. 7196 7197 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7198 request one row/column in a block, they must request all rows/columns that are in 7199 that block. For example, if the block size is 2 you cannot request just row 0 and 7200 column 0. 7201 7202 Fortran Note: 7203 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7204 7205 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7206 @*/ 7207 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7208 { 7209 PetscInt i; 7210 PetscBool eq; 7211 7212 PetscFunctionBegin; 7213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7214 PetscValidType(mat, 1); 7215 if (n) { 7216 PetscAssertPointer(irow, 3); 7217 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7218 PetscAssertPointer(icol, 4); 7219 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7220 } 7221 PetscAssertPointer(submat, 6); 7222 if (n && scall == MAT_REUSE_MATRIX) { 7223 PetscAssertPointer(*submat, 6); 7224 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7225 } 7226 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7227 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7228 MatCheckPreallocated(mat, 1); 7229 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7230 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7231 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7232 for (i = 0; i < n; i++) { 7233 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7234 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7235 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7236 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7237 if (mat->boundtocpu && mat->bindingpropagates) { 7238 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7239 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7240 } 7241 #endif 7242 } 7243 PetscFunctionReturn(PETSC_SUCCESS); 7244 } 7245 7246 /*@C 7247 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7248 7249 Collective 7250 7251 Input Parameters: 7252 + mat - the matrix 7253 . n - the number of submatrixes to be extracted 7254 . irow - index set of rows to extract 7255 . icol - index set of columns to extract 7256 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7257 7258 Output Parameter: 7259 . submat - the array of submatrices 7260 7261 Level: advanced 7262 7263 Note: 7264 This is used by `PCGASM` 7265 7266 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7267 @*/ 7268 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7269 { 7270 PetscInt i; 7271 PetscBool eq; 7272 7273 PetscFunctionBegin; 7274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7275 PetscValidType(mat, 1); 7276 if (n) { 7277 PetscAssertPointer(irow, 3); 7278 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7279 PetscAssertPointer(icol, 4); 7280 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7281 } 7282 PetscAssertPointer(submat, 6); 7283 if (n && scall == MAT_REUSE_MATRIX) { 7284 PetscAssertPointer(*submat, 6); 7285 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7286 } 7287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7288 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7289 MatCheckPreallocated(mat, 1); 7290 7291 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7292 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7293 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7294 for (i = 0; i < n; i++) { 7295 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7296 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7297 } 7298 PetscFunctionReturn(PETSC_SUCCESS); 7299 } 7300 7301 /*@C 7302 MatDestroyMatrices - Destroys an array of matrices. 7303 7304 Collective 7305 7306 Input Parameters: 7307 + n - the number of local matrices 7308 - mat - the matrices (this is a pointer to the array of matrices) 7309 7310 Level: advanced 7311 7312 Notes: 7313 Frees not only the matrices, but also the array that contains the matrices 7314 7315 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7316 7317 Fortran Note: 7318 Does not free the `mat` array. 7319 7320 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7321 @*/ 7322 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7323 { 7324 PetscInt i; 7325 7326 PetscFunctionBegin; 7327 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7328 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7329 PetscAssertPointer(mat, 2); 7330 7331 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7332 7333 /* memory is allocated even if n = 0 */ 7334 PetscCall(PetscFree(*mat)); 7335 PetscFunctionReturn(PETSC_SUCCESS); 7336 } 7337 7338 /*@C 7339 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7340 7341 Collective 7342 7343 Input Parameters: 7344 + n - the number of local matrices 7345 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7346 sequence of `MatCreateSubMatrices()`) 7347 7348 Level: advanced 7349 7350 Note: 7351 Frees not only the matrices, but also the array that contains the matrices 7352 7353 Fortran Note: 7354 Does not free the `mat` array. 7355 7356 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7357 @*/ 7358 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7359 { 7360 Mat mat0; 7361 7362 PetscFunctionBegin; 7363 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7364 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7365 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7366 PetscAssertPointer(mat, 2); 7367 7368 mat0 = (*mat)[0]; 7369 if (mat0 && mat0->ops->destroysubmatrices) { 7370 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7371 } else { 7372 PetscCall(MatDestroyMatrices(n, mat)); 7373 } 7374 PetscFunctionReturn(PETSC_SUCCESS); 7375 } 7376 7377 /*@ 7378 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7379 7380 Collective 7381 7382 Input Parameter: 7383 . mat - the matrix 7384 7385 Output Parameter: 7386 . matstruct - the sequential matrix with the nonzero structure of `mat` 7387 7388 Level: developer 7389 7390 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7391 @*/ 7392 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7393 { 7394 PetscFunctionBegin; 7395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7396 PetscAssertPointer(matstruct, 2); 7397 7398 PetscValidType(mat, 1); 7399 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7400 MatCheckPreallocated(mat, 1); 7401 7402 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7403 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7404 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7405 PetscFunctionReturn(PETSC_SUCCESS); 7406 } 7407 7408 /*@C 7409 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7410 7411 Collective 7412 7413 Input Parameter: 7414 . mat - the matrix 7415 7416 Level: advanced 7417 7418 Note: 7419 This is not needed, one can just call `MatDestroy()` 7420 7421 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7422 @*/ 7423 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7424 { 7425 PetscFunctionBegin; 7426 PetscAssertPointer(mat, 1); 7427 PetscCall(MatDestroy(mat)); 7428 PetscFunctionReturn(PETSC_SUCCESS); 7429 } 7430 7431 /*@ 7432 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7433 replaces the index sets by larger ones that represent submatrices with 7434 additional overlap. 7435 7436 Collective 7437 7438 Input Parameters: 7439 + mat - the matrix 7440 . n - the number of index sets 7441 . is - the array of index sets (these index sets will changed during the call) 7442 - ov - the additional overlap requested 7443 7444 Options Database Key: 7445 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7446 7447 Level: developer 7448 7449 Note: 7450 The computed overlap preserves the matrix block sizes when the blocks are square. 7451 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7452 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7453 7454 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7455 @*/ 7456 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7457 { 7458 PetscInt i, bs, cbs; 7459 7460 PetscFunctionBegin; 7461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7462 PetscValidType(mat, 1); 7463 PetscValidLogicalCollectiveInt(mat, n, 2); 7464 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7465 if (n) { 7466 PetscAssertPointer(is, 3); 7467 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7468 } 7469 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7470 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7471 MatCheckPreallocated(mat, 1); 7472 7473 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7474 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7475 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7476 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7477 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7478 if (bs == cbs) { 7479 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7480 } 7481 PetscFunctionReturn(PETSC_SUCCESS); 7482 } 7483 7484 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7485 7486 /*@ 7487 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7488 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7489 additional overlap. 7490 7491 Collective 7492 7493 Input Parameters: 7494 + mat - the matrix 7495 . n - the number of index sets 7496 . is - the array of index sets (these index sets will changed during the call) 7497 - ov - the additional overlap requested 7498 7499 ` Options Database Key: 7500 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7501 7502 Level: developer 7503 7504 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7505 @*/ 7506 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7507 { 7508 PetscInt i; 7509 7510 PetscFunctionBegin; 7511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7512 PetscValidType(mat, 1); 7513 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7514 if (n) { 7515 PetscAssertPointer(is, 3); 7516 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7517 } 7518 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7519 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7520 MatCheckPreallocated(mat, 1); 7521 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7522 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7523 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7524 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7525 PetscFunctionReturn(PETSC_SUCCESS); 7526 } 7527 7528 /*@ 7529 MatGetBlockSize - Returns the matrix block size. 7530 7531 Not Collective 7532 7533 Input Parameter: 7534 . mat - the matrix 7535 7536 Output Parameter: 7537 . bs - block size 7538 7539 Level: intermediate 7540 7541 Notes: 7542 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7543 7544 If the block size has not been set yet this routine returns 1. 7545 7546 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7547 @*/ 7548 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7549 { 7550 PetscFunctionBegin; 7551 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7552 PetscAssertPointer(bs, 2); 7553 *bs = PetscAbs(mat->rmap->bs); 7554 PetscFunctionReturn(PETSC_SUCCESS); 7555 } 7556 7557 /*@ 7558 MatGetBlockSizes - Returns the matrix block row and column sizes. 7559 7560 Not Collective 7561 7562 Input Parameter: 7563 . mat - the matrix 7564 7565 Output Parameters: 7566 + rbs - row block size 7567 - cbs - column block size 7568 7569 Level: intermediate 7570 7571 Notes: 7572 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7573 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7574 7575 If a block size has not been set yet this routine returns 1. 7576 7577 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7578 @*/ 7579 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7580 { 7581 PetscFunctionBegin; 7582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7583 if (rbs) PetscAssertPointer(rbs, 2); 7584 if (cbs) PetscAssertPointer(cbs, 3); 7585 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7586 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7587 PetscFunctionReturn(PETSC_SUCCESS); 7588 } 7589 7590 /*@ 7591 MatSetBlockSize - Sets the matrix block size. 7592 7593 Logically Collective 7594 7595 Input Parameters: 7596 + mat - the matrix 7597 - bs - block size 7598 7599 Level: intermediate 7600 7601 Notes: 7602 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7603 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7604 7605 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7606 is compatible with the matrix local sizes. 7607 7608 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7609 @*/ 7610 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7611 { 7612 PetscFunctionBegin; 7613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7614 PetscValidLogicalCollectiveInt(mat, bs, 2); 7615 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7616 PetscFunctionReturn(PETSC_SUCCESS); 7617 } 7618 7619 typedef struct { 7620 PetscInt n; 7621 IS *is; 7622 Mat *mat; 7623 PetscObjectState nonzerostate; 7624 Mat C; 7625 } EnvelopeData; 7626 7627 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7628 { 7629 EnvelopeData *edata = (EnvelopeData *)ptr; 7630 7631 PetscFunctionBegin; 7632 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7633 PetscCall(PetscFree(edata->is)); 7634 PetscCall(PetscFree(edata)); 7635 PetscFunctionReturn(PETSC_SUCCESS); 7636 } 7637 7638 /*@ 7639 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7640 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7641 7642 Collective 7643 7644 Input Parameter: 7645 . mat - the matrix 7646 7647 Level: intermediate 7648 7649 Notes: 7650 There can be zeros within the blocks 7651 7652 The blocks can overlap between processes, including laying on more than two processes 7653 7654 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7655 @*/ 7656 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7657 { 7658 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7659 PetscInt *diag, *odiag, sc; 7660 VecScatter scatter; 7661 PetscScalar *seqv; 7662 const PetscScalar *parv; 7663 const PetscInt *ia, *ja; 7664 PetscBool set, flag, done; 7665 Mat AA = mat, A; 7666 MPI_Comm comm; 7667 PetscMPIInt rank, size, tag; 7668 MPI_Status status; 7669 PetscContainer container; 7670 EnvelopeData *edata; 7671 Vec seq, par; 7672 IS isglobal; 7673 7674 PetscFunctionBegin; 7675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7676 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7677 if (!set || !flag) { 7678 /* TODO: only needs nonzero structure of transpose */ 7679 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7680 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7681 } 7682 PetscCall(MatAIJGetLocalMat(AA, &A)); 7683 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7684 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7685 7686 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7687 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7688 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7689 PetscCallMPI(MPI_Comm_size(comm, &size)); 7690 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7691 7692 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7693 7694 if (rank > 0) { 7695 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7696 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7697 } 7698 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7699 for (i = 0; i < n; i++) { 7700 env = PetscMax(env, ja[ia[i + 1] - 1]); 7701 II = rstart + i; 7702 if (env == II) { 7703 starts[lblocks] = tbs; 7704 sizes[lblocks++] = 1 + II - tbs; 7705 tbs = 1 + II; 7706 } 7707 } 7708 if (rank < size - 1) { 7709 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7710 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7711 } 7712 7713 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7714 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7715 PetscCall(MatDestroy(&A)); 7716 7717 PetscCall(PetscNew(&edata)); 7718 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7719 edata->n = lblocks; 7720 /* create IS needed for extracting blocks from the original matrix */ 7721 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7722 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7723 7724 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7725 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7726 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7727 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7728 PetscCall(MatSetType(edata->C, MATAIJ)); 7729 7730 /* Communicate the start and end of each row, from each block to the correct rank */ 7731 /* TODO: Use PetscSF instead of VecScatter */ 7732 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7733 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7734 PetscCall(VecGetArrayWrite(seq, &seqv)); 7735 for (PetscInt i = 0; i < lblocks; i++) { 7736 for (PetscInt j = 0; j < sizes[i]; j++) { 7737 seqv[cnt] = starts[i]; 7738 seqv[cnt + 1] = starts[i] + sizes[i]; 7739 cnt += 2; 7740 } 7741 } 7742 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7743 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7744 sc -= cnt; 7745 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7746 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7747 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7748 PetscCall(ISDestroy(&isglobal)); 7749 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7750 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7751 PetscCall(VecScatterDestroy(&scatter)); 7752 PetscCall(VecDestroy(&seq)); 7753 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7754 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7755 PetscCall(VecGetArrayRead(par, &parv)); 7756 cnt = 0; 7757 PetscCall(MatGetSize(mat, NULL, &n)); 7758 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7759 PetscInt start, end, d = 0, od = 0; 7760 7761 start = (PetscInt)PetscRealPart(parv[cnt]); 7762 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7763 cnt += 2; 7764 7765 if (start < cstart) { 7766 od += cstart - start + n - cend; 7767 d += cend - cstart; 7768 } else if (start < cend) { 7769 od += n - cend; 7770 d += cend - start; 7771 } else od += n - start; 7772 if (end <= cstart) { 7773 od -= cstart - end + n - cend; 7774 d -= cend - cstart; 7775 } else if (end < cend) { 7776 od -= n - cend; 7777 d -= cend - end; 7778 } else od -= n - end; 7779 7780 odiag[i] = od; 7781 diag[i] = d; 7782 } 7783 PetscCall(VecRestoreArrayRead(par, &parv)); 7784 PetscCall(VecDestroy(&par)); 7785 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7786 PetscCall(PetscFree2(diag, odiag)); 7787 PetscCall(PetscFree2(sizes, starts)); 7788 7789 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7790 PetscCall(PetscContainerSetPointer(container, edata)); 7791 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode (*)(void *))EnvelopeDataDestroy)); 7792 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7793 PetscCall(PetscObjectDereference((PetscObject)container)); 7794 PetscFunctionReturn(PETSC_SUCCESS); 7795 } 7796 7797 /*@ 7798 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7799 7800 Collective 7801 7802 Input Parameters: 7803 + A - the matrix 7804 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7805 7806 Output Parameter: 7807 . C - matrix with inverted block diagonal of `A` 7808 7809 Level: advanced 7810 7811 Note: 7812 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7813 7814 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7815 @*/ 7816 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7817 { 7818 PetscContainer container; 7819 EnvelopeData *edata; 7820 PetscObjectState nonzerostate; 7821 7822 PetscFunctionBegin; 7823 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7824 if (!container) { 7825 PetscCall(MatComputeVariableBlockEnvelope(A)); 7826 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7827 } 7828 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7829 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7830 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7831 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7832 7833 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7834 *C = edata->C; 7835 7836 for (PetscInt i = 0; i < edata->n; i++) { 7837 Mat D; 7838 PetscScalar *dvalues; 7839 7840 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7841 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7842 PetscCall(MatSeqDenseInvert(D)); 7843 PetscCall(MatDenseGetArray(D, &dvalues)); 7844 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7845 PetscCall(MatDestroy(&D)); 7846 } 7847 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7848 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7849 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7850 PetscFunctionReturn(PETSC_SUCCESS); 7851 } 7852 7853 /*@ 7854 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7855 7856 Not Collective 7857 7858 Input Parameters: 7859 + mat - the matrix 7860 . nblocks - the number of blocks on this process, each block can only exist on a single process 7861 - bsizes - the block sizes 7862 7863 Level: intermediate 7864 7865 Notes: 7866 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7867 7868 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. 7869 7870 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7871 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7872 @*/ 7873 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7874 { 7875 PetscInt ncnt = 0, nlocal; 7876 7877 PetscFunctionBegin; 7878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7879 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7880 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); 7881 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7882 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); 7883 PetscCall(PetscFree(mat->bsizes)); 7884 mat->nblocks = nblocks; 7885 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7886 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7887 PetscFunctionReturn(PETSC_SUCCESS); 7888 } 7889 7890 /*@C 7891 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7892 7893 Not Collective; No Fortran Support 7894 7895 Input Parameter: 7896 . mat - the matrix 7897 7898 Output Parameters: 7899 + nblocks - the number of blocks on this process 7900 - bsizes - the block sizes 7901 7902 Level: intermediate 7903 7904 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7905 @*/ 7906 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7907 { 7908 PetscFunctionBegin; 7909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7910 if (nblocks) *nblocks = mat->nblocks; 7911 if (bsizes) *bsizes = mat->bsizes; 7912 PetscFunctionReturn(PETSC_SUCCESS); 7913 } 7914 7915 /*@ 7916 MatSetBlockSizes - Sets the matrix block row and column sizes. 7917 7918 Logically Collective 7919 7920 Input Parameters: 7921 + mat - the matrix 7922 . rbs - row block size 7923 - cbs - column block size 7924 7925 Level: intermediate 7926 7927 Notes: 7928 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7929 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7930 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7931 7932 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7933 are compatible with the matrix local sizes. 7934 7935 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7936 7937 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7938 @*/ 7939 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7940 { 7941 PetscFunctionBegin; 7942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7943 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7944 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7945 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7946 if (mat->rmap->refcnt) { 7947 ISLocalToGlobalMapping l2g = NULL; 7948 PetscLayout nmap = NULL; 7949 7950 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7951 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7952 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7953 mat->rmap = nmap; 7954 mat->rmap->mapping = l2g; 7955 } 7956 if (mat->cmap->refcnt) { 7957 ISLocalToGlobalMapping l2g = NULL; 7958 PetscLayout nmap = NULL; 7959 7960 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7961 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7962 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7963 mat->cmap = nmap; 7964 mat->cmap->mapping = l2g; 7965 } 7966 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7967 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7968 PetscFunctionReturn(PETSC_SUCCESS); 7969 } 7970 7971 /*@ 7972 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7973 7974 Logically Collective 7975 7976 Input Parameters: 7977 + mat - the matrix 7978 . fromRow - matrix from which to copy row block size 7979 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7980 7981 Level: developer 7982 7983 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7984 @*/ 7985 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7986 { 7987 PetscFunctionBegin; 7988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7989 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7990 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7991 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7992 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7993 PetscFunctionReturn(PETSC_SUCCESS); 7994 } 7995 7996 /*@ 7997 MatResidual - Default routine to calculate the residual r = b - Ax 7998 7999 Collective 8000 8001 Input Parameters: 8002 + mat - the matrix 8003 . b - the right-hand-side 8004 - x - the approximate solution 8005 8006 Output Parameter: 8007 . r - location to store the residual 8008 8009 Level: developer 8010 8011 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8012 @*/ 8013 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8014 { 8015 PetscFunctionBegin; 8016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8017 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8018 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8019 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8020 PetscValidType(mat, 1); 8021 MatCheckPreallocated(mat, 1); 8022 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8023 if (!mat->ops->residual) { 8024 PetscCall(MatMult(mat, x, r)); 8025 PetscCall(VecAYPX(r, -1.0, b)); 8026 } else { 8027 PetscUseTypeMethod(mat, residual, b, x, r); 8028 } 8029 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8030 PetscFunctionReturn(PETSC_SUCCESS); 8031 } 8032 8033 /*MC 8034 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8035 8036 Synopsis: 8037 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8038 8039 Not Collective 8040 8041 Input Parameters: 8042 + A - the matrix 8043 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8044 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8045 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8046 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8047 always used. 8048 8049 Output Parameters: 8050 + n - number of local rows in the (possibly compressed) matrix 8051 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8052 . ja - the column indices 8053 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8054 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8055 8056 Level: developer 8057 8058 Note: 8059 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8060 8061 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8062 M*/ 8063 8064 /*MC 8065 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8066 8067 Synopsis: 8068 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8069 8070 Not Collective 8071 8072 Input Parameters: 8073 + A - the matrix 8074 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8075 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8076 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8077 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8078 always used. 8079 . n - number of local rows in the (possibly compressed) matrix 8080 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8081 . ja - the column indices 8082 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8083 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8084 8085 Level: developer 8086 8087 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8088 M*/ 8089 8090 /*@C 8091 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8092 8093 Collective 8094 8095 Input Parameters: 8096 + mat - the matrix 8097 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8098 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8099 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8100 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8101 always used. 8102 8103 Output Parameters: 8104 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8105 . 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 8106 . ja - the column indices, use `NULL` if not needed 8107 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8108 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8109 8110 Level: developer 8111 8112 Notes: 8113 You CANNOT change any of the ia[] or ja[] values. 8114 8115 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8116 8117 Fortran Notes: 8118 Use 8119 .vb 8120 PetscInt, pointer :: ia(:),ja(:) 8121 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8122 ! Access the ith and jth entries via ia(i) and ja(j) 8123 .ve 8124 8125 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8126 8127 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8128 @*/ 8129 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8130 { 8131 PetscFunctionBegin; 8132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8133 PetscValidType(mat, 1); 8134 if (n) PetscAssertPointer(n, 5); 8135 if (ia) PetscAssertPointer(ia, 6); 8136 if (ja) PetscAssertPointer(ja, 7); 8137 if (done) PetscAssertPointer(done, 8); 8138 MatCheckPreallocated(mat, 1); 8139 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8140 else { 8141 if (done) *done = PETSC_TRUE; 8142 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8143 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8144 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8145 } 8146 PetscFunctionReturn(PETSC_SUCCESS); 8147 } 8148 8149 /*@C 8150 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8151 8152 Collective 8153 8154 Input Parameters: 8155 + mat - the matrix 8156 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8157 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8158 symmetrized 8159 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8160 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8161 always used. 8162 . n - number of columns in the (possibly compressed) matrix 8163 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8164 - ja - the row indices 8165 8166 Output Parameter: 8167 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8168 8169 Level: developer 8170 8171 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8172 @*/ 8173 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8174 { 8175 PetscFunctionBegin; 8176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8177 PetscValidType(mat, 1); 8178 PetscAssertPointer(n, 5); 8179 if (ia) PetscAssertPointer(ia, 6); 8180 if (ja) PetscAssertPointer(ja, 7); 8181 PetscAssertPointer(done, 8); 8182 MatCheckPreallocated(mat, 1); 8183 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8184 else { 8185 *done = PETSC_TRUE; 8186 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8187 } 8188 PetscFunctionReturn(PETSC_SUCCESS); 8189 } 8190 8191 /*@C 8192 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8193 8194 Collective 8195 8196 Input Parameters: 8197 + mat - the matrix 8198 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8199 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8200 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8201 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8202 always used. 8203 . n - size of (possibly compressed) matrix 8204 . ia - the row pointers 8205 - ja - the column indices 8206 8207 Output Parameter: 8208 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8209 8210 Level: developer 8211 8212 Note: 8213 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8214 us of the array after it has been restored. If you pass `NULL`, it will 8215 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8216 8217 Fortran Note: 8218 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8219 8220 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8221 @*/ 8222 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8223 { 8224 PetscFunctionBegin; 8225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8226 PetscValidType(mat, 1); 8227 if (ia) PetscAssertPointer(ia, 6); 8228 if (ja) PetscAssertPointer(ja, 7); 8229 if (done) PetscAssertPointer(done, 8); 8230 MatCheckPreallocated(mat, 1); 8231 8232 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8233 else { 8234 if (done) *done = PETSC_TRUE; 8235 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8236 if (n) *n = 0; 8237 if (ia) *ia = NULL; 8238 if (ja) *ja = NULL; 8239 } 8240 PetscFunctionReturn(PETSC_SUCCESS); 8241 } 8242 8243 /*@C 8244 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8245 8246 Collective 8247 8248 Input Parameters: 8249 + mat - the matrix 8250 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8251 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8252 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8253 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8254 always used. 8255 8256 Output Parameters: 8257 + n - size of (possibly compressed) matrix 8258 . ia - the column pointers 8259 . ja - the row indices 8260 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8261 8262 Level: developer 8263 8264 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8265 @*/ 8266 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8267 { 8268 PetscFunctionBegin; 8269 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8270 PetscValidType(mat, 1); 8271 if (ia) PetscAssertPointer(ia, 6); 8272 if (ja) PetscAssertPointer(ja, 7); 8273 PetscAssertPointer(done, 8); 8274 MatCheckPreallocated(mat, 1); 8275 8276 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8277 else { 8278 *done = PETSC_TRUE; 8279 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8280 if (n) *n = 0; 8281 if (ia) *ia = NULL; 8282 if (ja) *ja = NULL; 8283 } 8284 PetscFunctionReturn(PETSC_SUCCESS); 8285 } 8286 8287 /*@ 8288 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8289 `MatGetColumnIJ()`. 8290 8291 Collective 8292 8293 Input Parameters: 8294 + mat - the matrix 8295 . ncolors - maximum color value 8296 . n - number of entries in colorarray 8297 - colorarray - array indicating color for each column 8298 8299 Output Parameter: 8300 . iscoloring - coloring generated using colorarray information 8301 8302 Level: developer 8303 8304 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8305 @*/ 8306 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8307 { 8308 PetscFunctionBegin; 8309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8310 PetscValidType(mat, 1); 8311 PetscAssertPointer(colorarray, 4); 8312 PetscAssertPointer(iscoloring, 5); 8313 MatCheckPreallocated(mat, 1); 8314 8315 if (!mat->ops->coloringpatch) { 8316 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8317 } else { 8318 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8319 } 8320 PetscFunctionReturn(PETSC_SUCCESS); 8321 } 8322 8323 /*@ 8324 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8325 8326 Logically Collective 8327 8328 Input Parameter: 8329 . mat - the factored matrix to be reset 8330 8331 Level: developer 8332 8333 Notes: 8334 This routine should be used only with factored matrices formed by in-place 8335 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8336 format). This option can save memory, for example, when solving nonlinear 8337 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8338 ILU(0) preconditioner. 8339 8340 One can specify in-place ILU(0) factorization by calling 8341 .vb 8342 PCType(pc,PCILU); 8343 PCFactorSeUseInPlace(pc); 8344 .ve 8345 or by using the options -pc_type ilu -pc_factor_in_place 8346 8347 In-place factorization ILU(0) can also be used as a local 8348 solver for the blocks within the block Jacobi or additive Schwarz 8349 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8350 for details on setting local solver options. 8351 8352 Most users should employ the `KSP` interface for linear solvers 8353 instead of working directly with matrix algebra routines such as this. 8354 See, e.g., `KSPCreate()`. 8355 8356 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8357 @*/ 8358 PetscErrorCode MatSetUnfactored(Mat mat) 8359 { 8360 PetscFunctionBegin; 8361 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8362 PetscValidType(mat, 1); 8363 MatCheckPreallocated(mat, 1); 8364 mat->factortype = MAT_FACTOR_NONE; 8365 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8366 PetscUseTypeMethod(mat, setunfactored); 8367 PetscFunctionReturn(PETSC_SUCCESS); 8368 } 8369 8370 /*MC 8371 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8372 8373 Synopsis: 8374 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8375 8376 Not Collective 8377 8378 Input Parameter: 8379 . x - matrix 8380 8381 Output Parameters: 8382 + xx_v - the Fortran pointer to the array 8383 - ierr - error code 8384 8385 Example of Usage: 8386 .vb 8387 PetscScalar, pointer xx_v(:,:) 8388 .... 8389 call MatDenseGetArrayF90(x,xx_v,ierr) 8390 a = xx_v(3) 8391 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8392 .ve 8393 8394 Level: advanced 8395 8396 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8397 M*/ 8398 8399 /*MC 8400 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8401 accessed with `MatDenseGetArrayF90()`. 8402 8403 Synopsis: 8404 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8405 8406 Not Collective 8407 8408 Input Parameters: 8409 + x - matrix 8410 - xx_v - the Fortran90 pointer to the array 8411 8412 Output Parameter: 8413 . ierr - error code 8414 8415 Example of Usage: 8416 .vb 8417 PetscScalar, pointer xx_v(:,:) 8418 .... 8419 call MatDenseGetArrayF90(x,xx_v,ierr) 8420 a = xx_v(3) 8421 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8422 .ve 8423 8424 Level: advanced 8425 8426 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8427 M*/ 8428 8429 /*MC 8430 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8431 8432 Synopsis: 8433 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8434 8435 Not Collective 8436 8437 Input Parameter: 8438 . x - matrix 8439 8440 Output Parameters: 8441 + xx_v - the Fortran pointer to the array 8442 - ierr - error code 8443 8444 Example of Usage: 8445 .vb 8446 PetscScalar, pointer xx_v(:) 8447 .... 8448 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8449 a = xx_v(3) 8450 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8451 .ve 8452 8453 Level: advanced 8454 8455 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8456 M*/ 8457 8458 /*MC 8459 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8460 accessed with `MatSeqAIJGetArrayF90()`. 8461 8462 Synopsis: 8463 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8464 8465 Not Collective 8466 8467 Input Parameters: 8468 + x - matrix 8469 - xx_v - the Fortran90 pointer to the array 8470 8471 Output Parameter: 8472 . ierr - error code 8473 8474 Example of Usage: 8475 .vb 8476 PetscScalar, pointer xx_v(:) 8477 .... 8478 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8479 a = xx_v(3) 8480 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8481 .ve 8482 8483 Level: advanced 8484 8485 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8486 M*/ 8487 8488 /*@ 8489 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8490 as the original matrix. 8491 8492 Collective 8493 8494 Input Parameters: 8495 + mat - the original matrix 8496 . isrow - parallel `IS` containing the rows this processor should obtain 8497 . 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. 8498 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8499 8500 Output Parameter: 8501 . newmat - the new submatrix, of the same type as the original matrix 8502 8503 Level: advanced 8504 8505 Notes: 8506 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8507 8508 Some matrix types place restrictions on the row and column indices, such 8509 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; 8510 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8511 8512 The index sets may not have duplicate entries. 8513 8514 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8515 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8516 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8517 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8518 you are finished using it. 8519 8520 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8521 the input matrix. 8522 8523 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8524 8525 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8526 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8527 8528 Example usage: 8529 Consider the following 8x8 matrix with 34 non-zero values, that is 8530 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8531 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8532 as follows 8533 .vb 8534 1 2 0 | 0 3 0 | 0 4 8535 Proc0 0 5 6 | 7 0 0 | 8 0 8536 9 0 10 | 11 0 0 | 12 0 8537 ------------------------------------- 8538 13 0 14 | 15 16 17 | 0 0 8539 Proc1 0 18 0 | 19 20 21 | 0 0 8540 0 0 0 | 22 23 0 | 24 0 8541 ------------------------------------- 8542 Proc2 25 26 27 | 0 0 28 | 29 0 8543 30 0 0 | 31 32 33 | 0 34 8544 .ve 8545 8546 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8547 8548 .vb 8549 2 0 | 0 3 0 | 0 8550 Proc0 5 6 | 7 0 0 | 8 8551 ------------------------------- 8552 Proc1 18 0 | 19 20 21 | 0 8553 ------------------------------- 8554 Proc2 26 27 | 0 0 28 | 29 8555 0 0 | 31 32 33 | 0 8556 .ve 8557 8558 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8559 @*/ 8560 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8561 { 8562 PetscMPIInt size; 8563 Mat *local; 8564 IS iscoltmp; 8565 PetscBool flg; 8566 8567 PetscFunctionBegin; 8568 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8569 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8570 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8571 PetscAssertPointer(newmat, 5); 8572 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8573 PetscValidType(mat, 1); 8574 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8575 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8576 8577 MatCheckPreallocated(mat, 1); 8578 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8579 8580 if (!iscol || isrow == iscol) { 8581 PetscBool stride; 8582 PetscMPIInt grabentirematrix = 0, grab; 8583 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8584 if (stride) { 8585 PetscInt first, step, n, rstart, rend; 8586 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8587 if (step == 1) { 8588 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8589 if (rstart == first) { 8590 PetscCall(ISGetLocalSize(isrow, &n)); 8591 if (n == rend - rstart) grabentirematrix = 1; 8592 } 8593 } 8594 } 8595 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8596 if (grab) { 8597 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8598 if (cll == MAT_INITIAL_MATRIX) { 8599 *newmat = mat; 8600 PetscCall(PetscObjectReference((PetscObject)mat)); 8601 } 8602 PetscFunctionReturn(PETSC_SUCCESS); 8603 } 8604 } 8605 8606 if (!iscol) { 8607 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8608 } else { 8609 iscoltmp = iscol; 8610 } 8611 8612 /* if original matrix is on just one processor then use submatrix generated */ 8613 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8614 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8615 goto setproperties; 8616 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8617 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8618 *newmat = *local; 8619 PetscCall(PetscFree(local)); 8620 goto setproperties; 8621 } else if (!mat->ops->createsubmatrix) { 8622 /* Create a new matrix type that implements the operation using the full matrix */ 8623 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8624 switch (cll) { 8625 case MAT_INITIAL_MATRIX: 8626 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8627 break; 8628 case MAT_REUSE_MATRIX: 8629 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8630 break; 8631 default: 8632 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8633 } 8634 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8635 goto setproperties; 8636 } 8637 8638 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8639 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8640 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8641 8642 setproperties: 8643 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8644 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8645 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8646 } 8647 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8648 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8649 PetscFunctionReturn(PETSC_SUCCESS); 8650 } 8651 8652 /*@ 8653 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8654 8655 Not Collective 8656 8657 Input Parameters: 8658 + A - the matrix we wish to propagate options from 8659 - B - the matrix we wish to propagate options to 8660 8661 Level: beginner 8662 8663 Note: 8664 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8665 8666 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8667 @*/ 8668 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8669 { 8670 PetscFunctionBegin; 8671 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8672 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8673 B->symmetry_eternal = A->symmetry_eternal; 8674 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8675 B->symmetric = A->symmetric; 8676 B->structurally_symmetric = A->structurally_symmetric; 8677 B->spd = A->spd; 8678 B->hermitian = A->hermitian; 8679 PetscFunctionReturn(PETSC_SUCCESS); 8680 } 8681 8682 /*@ 8683 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8684 used during the assembly process to store values that belong to 8685 other processors. 8686 8687 Not Collective 8688 8689 Input Parameters: 8690 + mat - the matrix 8691 . size - the initial size of the stash. 8692 - bsize - the initial size of the block-stash(if used). 8693 8694 Options Database Keys: 8695 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8696 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8697 8698 Level: intermediate 8699 8700 Notes: 8701 The block-stash is used for values set with `MatSetValuesBlocked()` while 8702 the stash is used for values set with `MatSetValues()` 8703 8704 Run with the option -info and look for output of the form 8705 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8706 to determine the appropriate value, MM, to use for size and 8707 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8708 to determine the value, BMM to use for bsize 8709 8710 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8711 @*/ 8712 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8713 { 8714 PetscFunctionBegin; 8715 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8716 PetscValidType(mat, 1); 8717 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8718 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8719 PetscFunctionReturn(PETSC_SUCCESS); 8720 } 8721 8722 /*@ 8723 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8724 the matrix 8725 8726 Neighbor-wise Collective 8727 8728 Input Parameters: 8729 + A - the matrix 8730 . x - the vector to be multiplied by the interpolation operator 8731 - y - the vector to be added to the result 8732 8733 Output Parameter: 8734 . w - the resulting vector 8735 8736 Level: intermediate 8737 8738 Notes: 8739 `w` may be the same vector as `y`. 8740 8741 This allows one to use either the restriction or interpolation (its transpose) 8742 matrix to do the interpolation 8743 8744 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8745 @*/ 8746 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8747 { 8748 PetscInt M, N, Ny; 8749 8750 PetscFunctionBegin; 8751 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8752 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8753 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8754 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8755 PetscCall(MatGetSize(A, &M, &N)); 8756 PetscCall(VecGetSize(y, &Ny)); 8757 if (M == Ny) { 8758 PetscCall(MatMultAdd(A, x, y, w)); 8759 } else { 8760 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8761 } 8762 PetscFunctionReturn(PETSC_SUCCESS); 8763 } 8764 8765 /*@ 8766 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8767 the matrix 8768 8769 Neighbor-wise Collective 8770 8771 Input Parameters: 8772 + A - the matrix 8773 - x - the vector to be interpolated 8774 8775 Output Parameter: 8776 . y - the resulting vector 8777 8778 Level: intermediate 8779 8780 Note: 8781 This allows one to use either the restriction or interpolation (its transpose) 8782 matrix to do the interpolation 8783 8784 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8785 @*/ 8786 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8787 { 8788 PetscInt M, N, Ny; 8789 8790 PetscFunctionBegin; 8791 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8792 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8793 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8794 PetscCall(MatGetSize(A, &M, &N)); 8795 PetscCall(VecGetSize(y, &Ny)); 8796 if (M == Ny) { 8797 PetscCall(MatMult(A, x, y)); 8798 } else { 8799 PetscCall(MatMultTranspose(A, x, y)); 8800 } 8801 PetscFunctionReturn(PETSC_SUCCESS); 8802 } 8803 8804 /*@ 8805 MatRestrict - $y = A*x$ or $A^T*x$ 8806 8807 Neighbor-wise Collective 8808 8809 Input Parameters: 8810 + A - the matrix 8811 - x - the vector to be restricted 8812 8813 Output Parameter: 8814 . y - the resulting vector 8815 8816 Level: intermediate 8817 8818 Note: 8819 This allows one to use either the restriction or interpolation (its transpose) 8820 matrix to do the restriction 8821 8822 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8823 @*/ 8824 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8825 { 8826 PetscInt M, N, Nx; 8827 8828 PetscFunctionBegin; 8829 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8830 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8831 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8832 PetscCall(MatGetSize(A, &M, &N)); 8833 PetscCall(VecGetSize(x, &Nx)); 8834 if (M == Nx) { 8835 PetscCall(MatMultTranspose(A, x, y)); 8836 } else { 8837 PetscCall(MatMult(A, x, y)); 8838 } 8839 PetscFunctionReturn(PETSC_SUCCESS); 8840 } 8841 8842 /*@ 8843 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8844 8845 Neighbor-wise Collective 8846 8847 Input Parameters: 8848 + A - the matrix 8849 . x - the input dense matrix to be multiplied 8850 - w - the input dense matrix to be added to the result 8851 8852 Output Parameter: 8853 . y - the output dense matrix 8854 8855 Level: intermediate 8856 8857 Note: 8858 This allows one to use either the restriction or interpolation (its transpose) 8859 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8860 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8861 8862 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8863 @*/ 8864 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8865 { 8866 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8867 PetscBool trans = PETSC_TRUE; 8868 MatReuse reuse = MAT_INITIAL_MATRIX; 8869 8870 PetscFunctionBegin; 8871 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8872 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8873 PetscValidType(x, 2); 8874 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8875 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8876 PetscCall(MatGetSize(A, &M, &N)); 8877 PetscCall(MatGetSize(x, &Mx, &Nx)); 8878 if (N == Mx) trans = PETSC_FALSE; 8879 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); 8880 Mo = trans ? N : M; 8881 if (*y) { 8882 PetscCall(MatGetSize(*y, &My, &Ny)); 8883 if (Mo == My && Nx == Ny) { 8884 reuse = MAT_REUSE_MATRIX; 8885 } else { 8886 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); 8887 PetscCall(MatDestroy(y)); 8888 } 8889 } 8890 8891 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8892 PetscBool flg; 8893 8894 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8895 if (w) { 8896 PetscInt My, Ny, Mw, Nw; 8897 8898 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8899 PetscCall(MatGetSize(*y, &My, &Ny)); 8900 PetscCall(MatGetSize(w, &Mw, &Nw)); 8901 if (!flg || My != Mw || Ny != Nw) w = NULL; 8902 } 8903 if (!w) { 8904 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8905 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8906 PetscCall(PetscObjectDereference((PetscObject)w)); 8907 } else { 8908 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8909 } 8910 } 8911 if (!trans) { 8912 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8913 } else { 8914 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8915 } 8916 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8917 PetscFunctionReturn(PETSC_SUCCESS); 8918 } 8919 8920 /*@ 8921 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8922 8923 Neighbor-wise Collective 8924 8925 Input Parameters: 8926 + A - the matrix 8927 - x - the input dense matrix 8928 8929 Output Parameter: 8930 . y - the output dense matrix 8931 8932 Level: intermediate 8933 8934 Note: 8935 This allows one to use either the restriction or interpolation (its transpose) 8936 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8937 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8938 8939 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8940 @*/ 8941 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8942 { 8943 PetscFunctionBegin; 8944 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8945 PetscFunctionReturn(PETSC_SUCCESS); 8946 } 8947 8948 /*@ 8949 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8950 8951 Neighbor-wise Collective 8952 8953 Input Parameters: 8954 + A - the matrix 8955 - x - the input dense matrix 8956 8957 Output Parameter: 8958 . y - the output dense matrix 8959 8960 Level: intermediate 8961 8962 Note: 8963 This allows one to use either the restriction or interpolation (its transpose) 8964 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8965 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8966 8967 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8968 @*/ 8969 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8970 { 8971 PetscFunctionBegin; 8972 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8973 PetscFunctionReturn(PETSC_SUCCESS); 8974 } 8975 8976 /*@ 8977 MatGetNullSpace - retrieves the null space of a matrix. 8978 8979 Logically Collective 8980 8981 Input Parameters: 8982 + mat - the matrix 8983 - nullsp - the null space object 8984 8985 Level: developer 8986 8987 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8988 @*/ 8989 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8990 { 8991 PetscFunctionBegin; 8992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8993 PetscAssertPointer(nullsp, 2); 8994 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8995 PetscFunctionReturn(PETSC_SUCCESS); 8996 } 8997 8998 /*@C 8999 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9000 9001 Logically Collective 9002 9003 Input Parameters: 9004 + n - the number of matrices 9005 - mat - the array of matrices 9006 9007 Output Parameters: 9008 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9009 9010 Level: developer 9011 9012 Note: 9013 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9014 9015 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9016 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9017 @*/ 9018 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9019 { 9020 PetscFunctionBegin; 9021 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9022 PetscAssertPointer(mat, 2); 9023 PetscAssertPointer(nullsp, 3); 9024 9025 PetscCall(PetscCalloc1(3 * n, nullsp)); 9026 for (PetscInt i = 0; i < n; i++) { 9027 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9028 (*nullsp)[i] = mat[i]->nullsp; 9029 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9030 (*nullsp)[n + i] = mat[i]->nearnullsp; 9031 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9032 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9033 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9034 } 9035 PetscFunctionReturn(PETSC_SUCCESS); 9036 } 9037 9038 /*@C 9039 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9040 9041 Logically Collective 9042 9043 Input Parameters: 9044 + n - the number of matrices 9045 . mat - the array of matrices 9046 - nullsp - an array of null spaces 9047 9048 Level: developer 9049 9050 Note: 9051 Call `MatGetNullSpaces()` to create `nullsp` 9052 9053 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9054 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9055 @*/ 9056 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9057 { 9058 PetscFunctionBegin; 9059 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9060 PetscAssertPointer(mat, 2); 9061 PetscAssertPointer(nullsp, 3); 9062 PetscAssertPointer(*nullsp, 3); 9063 9064 for (PetscInt i = 0; i < n; i++) { 9065 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9066 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9067 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9068 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9069 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9070 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9071 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9072 } 9073 PetscCall(PetscFree(*nullsp)); 9074 PetscFunctionReturn(PETSC_SUCCESS); 9075 } 9076 9077 /*@ 9078 MatSetNullSpace - attaches a null space to a matrix. 9079 9080 Logically Collective 9081 9082 Input Parameters: 9083 + mat - the matrix 9084 - nullsp - the null space object 9085 9086 Level: advanced 9087 9088 Notes: 9089 This null space is used by the `KSP` linear solvers to solve singular systems. 9090 9091 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` 9092 9093 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 9094 to zero but the linear system will still be solved in a least squares sense. 9095 9096 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9097 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)$. 9098 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 9099 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 9100 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$). 9101 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9102 9103 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9104 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9105 routine also automatically calls `MatSetTransposeNullSpace()`. 9106 9107 The user should call `MatNullSpaceDestroy()`. 9108 9109 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9110 `KSPSetPCSide()` 9111 @*/ 9112 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9113 { 9114 PetscFunctionBegin; 9115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9116 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9117 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9118 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9119 mat->nullsp = nullsp; 9120 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9121 PetscFunctionReturn(PETSC_SUCCESS); 9122 } 9123 9124 /*@ 9125 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9126 9127 Logically Collective 9128 9129 Input Parameters: 9130 + mat - the matrix 9131 - nullsp - the null space object 9132 9133 Level: developer 9134 9135 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9136 @*/ 9137 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9138 { 9139 PetscFunctionBegin; 9140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9141 PetscValidType(mat, 1); 9142 PetscAssertPointer(nullsp, 2); 9143 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9144 PetscFunctionReturn(PETSC_SUCCESS); 9145 } 9146 9147 /*@ 9148 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9149 9150 Logically Collective 9151 9152 Input Parameters: 9153 + mat - the matrix 9154 - nullsp - the null space object 9155 9156 Level: advanced 9157 9158 Notes: 9159 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9160 9161 See `MatSetNullSpace()` 9162 9163 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9164 @*/ 9165 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9166 { 9167 PetscFunctionBegin; 9168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9169 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9170 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9171 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9172 mat->transnullsp = nullsp; 9173 PetscFunctionReturn(PETSC_SUCCESS); 9174 } 9175 9176 /*@ 9177 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9178 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9179 9180 Logically Collective 9181 9182 Input Parameters: 9183 + mat - the matrix 9184 - nullsp - the null space object 9185 9186 Level: advanced 9187 9188 Notes: 9189 Overwrites any previous near null space that may have been attached 9190 9191 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9192 9193 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9194 @*/ 9195 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9196 { 9197 PetscFunctionBegin; 9198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9199 PetscValidType(mat, 1); 9200 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9201 MatCheckPreallocated(mat, 1); 9202 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9203 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9204 mat->nearnullsp = nullsp; 9205 PetscFunctionReturn(PETSC_SUCCESS); 9206 } 9207 9208 /*@ 9209 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9210 9211 Not Collective 9212 9213 Input Parameter: 9214 . mat - the matrix 9215 9216 Output Parameter: 9217 . nullsp - the null space object, `NULL` if not set 9218 9219 Level: advanced 9220 9221 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9222 @*/ 9223 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9224 { 9225 PetscFunctionBegin; 9226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9227 PetscValidType(mat, 1); 9228 PetscAssertPointer(nullsp, 2); 9229 MatCheckPreallocated(mat, 1); 9230 *nullsp = mat->nearnullsp; 9231 PetscFunctionReturn(PETSC_SUCCESS); 9232 } 9233 9234 /*@ 9235 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9236 9237 Collective 9238 9239 Input Parameters: 9240 + mat - the matrix 9241 . row - row/column permutation 9242 - info - information on desired factorization process 9243 9244 Level: developer 9245 9246 Notes: 9247 Probably really in-place only when level of fill is zero, otherwise allocates 9248 new space to store factored matrix and deletes previous memory. 9249 9250 Most users should employ the `KSP` interface for linear solvers 9251 instead of working directly with matrix algebra routines such as this. 9252 See, e.g., `KSPCreate()`. 9253 9254 Developer Note: 9255 The Fortran interface is not autogenerated as the 9256 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9257 9258 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9259 @*/ 9260 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9261 { 9262 PetscFunctionBegin; 9263 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9264 PetscValidType(mat, 1); 9265 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9266 PetscAssertPointer(info, 3); 9267 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9268 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9269 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9270 MatCheckPreallocated(mat, 1); 9271 PetscUseTypeMethod(mat, iccfactor, row, info); 9272 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9273 PetscFunctionReturn(PETSC_SUCCESS); 9274 } 9275 9276 /*@ 9277 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9278 ghosted ones. 9279 9280 Not Collective 9281 9282 Input Parameters: 9283 + mat - the matrix 9284 - diag - the diagonal values, including ghost ones 9285 9286 Level: developer 9287 9288 Notes: 9289 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9290 9291 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9292 9293 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9294 @*/ 9295 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9296 { 9297 PetscMPIInt size; 9298 9299 PetscFunctionBegin; 9300 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9301 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9302 PetscValidType(mat, 1); 9303 9304 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9305 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9306 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9307 if (size == 1) { 9308 PetscInt n, m; 9309 PetscCall(VecGetSize(diag, &n)); 9310 PetscCall(MatGetSize(mat, NULL, &m)); 9311 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9312 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9313 } else { 9314 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9315 } 9316 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9317 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9318 PetscFunctionReturn(PETSC_SUCCESS); 9319 } 9320 9321 /*@ 9322 MatGetInertia - Gets the inertia from a factored matrix 9323 9324 Collective 9325 9326 Input Parameter: 9327 . mat - the matrix 9328 9329 Output Parameters: 9330 + nneg - number of negative eigenvalues 9331 . nzero - number of zero eigenvalues 9332 - npos - number of positive eigenvalues 9333 9334 Level: advanced 9335 9336 Note: 9337 Matrix must have been factored by `MatCholeskyFactor()` 9338 9339 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9340 @*/ 9341 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9342 { 9343 PetscFunctionBegin; 9344 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9345 PetscValidType(mat, 1); 9346 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9347 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9348 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9349 PetscFunctionReturn(PETSC_SUCCESS); 9350 } 9351 9352 /*@C 9353 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9354 9355 Neighbor-wise Collective 9356 9357 Input Parameters: 9358 + mat - the factored matrix obtained with `MatGetFactor()` 9359 - b - the right-hand-side vectors 9360 9361 Output Parameter: 9362 . x - the result vectors 9363 9364 Level: developer 9365 9366 Note: 9367 The vectors `b` and `x` cannot be the same. I.e., one cannot 9368 call `MatSolves`(A,x,x). 9369 9370 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9371 @*/ 9372 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9373 { 9374 PetscFunctionBegin; 9375 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9376 PetscValidType(mat, 1); 9377 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9378 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9379 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9380 9381 MatCheckPreallocated(mat, 1); 9382 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9383 PetscUseTypeMethod(mat, solves, b, x); 9384 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9385 PetscFunctionReturn(PETSC_SUCCESS); 9386 } 9387 9388 /*@ 9389 MatIsSymmetric - Test whether a matrix is symmetric 9390 9391 Collective 9392 9393 Input Parameters: 9394 + A - the matrix to test 9395 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9396 9397 Output Parameter: 9398 . flg - the result 9399 9400 Level: intermediate 9401 9402 Notes: 9403 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9404 9405 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9406 9407 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9408 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9409 9410 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9411 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9412 @*/ 9413 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9414 { 9415 PetscFunctionBegin; 9416 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9417 PetscAssertPointer(flg, 3); 9418 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9419 else { 9420 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9421 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9422 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9423 } 9424 PetscFunctionReturn(PETSC_SUCCESS); 9425 } 9426 9427 /*@ 9428 MatIsHermitian - Test whether a matrix is Hermitian 9429 9430 Collective 9431 9432 Input Parameters: 9433 + A - the matrix to test 9434 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9435 9436 Output Parameter: 9437 . flg - the result 9438 9439 Level: intermediate 9440 9441 Notes: 9442 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9443 9444 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9445 9446 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9447 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9448 9449 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9450 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9451 @*/ 9452 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9453 { 9454 PetscFunctionBegin; 9455 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9456 PetscAssertPointer(flg, 3); 9457 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9458 else { 9459 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9460 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9461 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9462 } 9463 PetscFunctionReturn(PETSC_SUCCESS); 9464 } 9465 9466 /*@ 9467 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9468 9469 Not Collective 9470 9471 Input Parameter: 9472 . A - the matrix to check 9473 9474 Output Parameters: 9475 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9476 - flg - the result (only valid if set is `PETSC_TRUE`) 9477 9478 Level: advanced 9479 9480 Notes: 9481 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9482 if you want it explicitly checked 9483 9484 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9485 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9486 9487 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9488 @*/ 9489 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9490 { 9491 PetscFunctionBegin; 9492 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9493 PetscAssertPointer(set, 2); 9494 PetscAssertPointer(flg, 3); 9495 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9496 *set = PETSC_TRUE; 9497 *flg = PetscBool3ToBool(A->symmetric); 9498 } else { 9499 *set = PETSC_FALSE; 9500 } 9501 PetscFunctionReturn(PETSC_SUCCESS); 9502 } 9503 9504 /*@ 9505 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9506 9507 Not Collective 9508 9509 Input Parameter: 9510 . A - the matrix to check 9511 9512 Output Parameters: 9513 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9514 - flg - the result (only valid if set is `PETSC_TRUE`) 9515 9516 Level: advanced 9517 9518 Notes: 9519 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9520 9521 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9522 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9523 9524 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9525 @*/ 9526 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9527 { 9528 PetscFunctionBegin; 9529 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9530 PetscAssertPointer(set, 2); 9531 PetscAssertPointer(flg, 3); 9532 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9533 *set = PETSC_TRUE; 9534 *flg = PetscBool3ToBool(A->spd); 9535 } else { 9536 *set = PETSC_FALSE; 9537 } 9538 PetscFunctionReturn(PETSC_SUCCESS); 9539 } 9540 9541 /*@ 9542 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9543 9544 Not Collective 9545 9546 Input Parameter: 9547 . A - the matrix to check 9548 9549 Output Parameters: 9550 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9551 - flg - the result (only valid if set is `PETSC_TRUE`) 9552 9553 Level: advanced 9554 9555 Notes: 9556 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9557 if you want it explicitly checked 9558 9559 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9560 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9561 9562 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9563 @*/ 9564 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9565 { 9566 PetscFunctionBegin; 9567 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9568 PetscAssertPointer(set, 2); 9569 PetscAssertPointer(flg, 3); 9570 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9571 *set = PETSC_TRUE; 9572 *flg = PetscBool3ToBool(A->hermitian); 9573 } else { 9574 *set = PETSC_FALSE; 9575 } 9576 PetscFunctionReturn(PETSC_SUCCESS); 9577 } 9578 9579 /*@ 9580 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9581 9582 Collective 9583 9584 Input Parameter: 9585 . A - the matrix to test 9586 9587 Output Parameter: 9588 . flg - the result 9589 9590 Level: intermediate 9591 9592 Notes: 9593 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9594 9595 One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally 9596 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9597 9598 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9599 @*/ 9600 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9601 { 9602 PetscFunctionBegin; 9603 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9604 PetscAssertPointer(flg, 2); 9605 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9606 *flg = PetscBool3ToBool(A->structurally_symmetric); 9607 } else { 9608 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9609 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9610 } 9611 PetscFunctionReturn(PETSC_SUCCESS); 9612 } 9613 9614 /*@ 9615 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9616 9617 Not Collective 9618 9619 Input Parameter: 9620 . A - the matrix to check 9621 9622 Output Parameters: 9623 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9624 - flg - the result (only valid if set is PETSC_TRUE) 9625 9626 Level: advanced 9627 9628 Notes: 9629 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 9630 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9631 9632 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9633 9634 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9635 @*/ 9636 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9637 { 9638 PetscFunctionBegin; 9639 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9640 PetscAssertPointer(set, 2); 9641 PetscAssertPointer(flg, 3); 9642 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9643 *set = PETSC_TRUE; 9644 *flg = PetscBool3ToBool(A->structurally_symmetric); 9645 } else { 9646 *set = PETSC_FALSE; 9647 } 9648 PetscFunctionReturn(PETSC_SUCCESS); 9649 } 9650 9651 /*@ 9652 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9653 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9654 9655 Not Collective 9656 9657 Input Parameter: 9658 . mat - the matrix 9659 9660 Output Parameters: 9661 + nstash - the size of the stash 9662 . reallocs - the number of additional mallocs incurred. 9663 . bnstash - the size of the block stash 9664 - breallocs - the number of additional mallocs incurred.in the block stash 9665 9666 Level: advanced 9667 9668 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9669 @*/ 9670 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9671 { 9672 PetscFunctionBegin; 9673 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9674 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9675 PetscFunctionReturn(PETSC_SUCCESS); 9676 } 9677 9678 /*@ 9679 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9680 parallel layout, `PetscLayout` for rows and columns 9681 9682 Collective 9683 9684 Input Parameter: 9685 . mat - the matrix 9686 9687 Output Parameters: 9688 + right - (optional) vector that the matrix can be multiplied against 9689 - left - (optional) vector that the matrix vector product can be stored in 9690 9691 Level: advanced 9692 9693 Notes: 9694 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()`. 9695 9696 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9697 9698 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9699 @*/ 9700 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9701 { 9702 PetscFunctionBegin; 9703 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9704 PetscValidType(mat, 1); 9705 if (mat->ops->getvecs) { 9706 PetscUseTypeMethod(mat, getvecs, right, left); 9707 } else { 9708 if (right) { 9709 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9710 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9711 PetscCall(VecSetType(*right, mat->defaultvectype)); 9712 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9713 if (mat->boundtocpu && mat->bindingpropagates) { 9714 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9715 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9716 } 9717 #endif 9718 } 9719 if (left) { 9720 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9721 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9722 PetscCall(VecSetType(*left, mat->defaultvectype)); 9723 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9724 if (mat->boundtocpu && mat->bindingpropagates) { 9725 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9726 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9727 } 9728 #endif 9729 } 9730 } 9731 PetscFunctionReturn(PETSC_SUCCESS); 9732 } 9733 9734 /*@ 9735 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9736 with default values. 9737 9738 Not Collective 9739 9740 Input Parameter: 9741 . info - the `MatFactorInfo` data structure 9742 9743 Level: developer 9744 9745 Notes: 9746 The solvers are generally used through the `KSP` and `PC` objects, for example 9747 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9748 9749 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9750 9751 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9752 @*/ 9753 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9754 { 9755 PetscFunctionBegin; 9756 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9757 PetscFunctionReturn(PETSC_SUCCESS); 9758 } 9759 9760 /*@ 9761 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9762 9763 Collective 9764 9765 Input Parameters: 9766 + mat - the factored matrix 9767 - is - the index set defining the Schur indices (0-based) 9768 9769 Level: advanced 9770 9771 Notes: 9772 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9773 9774 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9775 9776 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9777 9778 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9779 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9780 @*/ 9781 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9782 { 9783 PetscErrorCode (*f)(Mat, IS); 9784 9785 PetscFunctionBegin; 9786 PetscValidType(mat, 1); 9787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9788 PetscValidType(is, 2); 9789 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9790 PetscCheckSameComm(mat, 1, is, 2); 9791 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9792 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9793 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9794 PetscCall(MatDestroy(&mat->schur)); 9795 PetscCall((*f)(mat, is)); 9796 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9797 PetscFunctionReturn(PETSC_SUCCESS); 9798 } 9799 9800 /*@ 9801 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9802 9803 Logically Collective 9804 9805 Input Parameters: 9806 + F - the factored matrix obtained by calling `MatGetFactor()` 9807 . S - location where to return the Schur complement, can be `NULL` 9808 - status - the status of the Schur complement matrix, can be `NULL` 9809 9810 Level: advanced 9811 9812 Notes: 9813 You must call `MatFactorSetSchurIS()` before calling this routine. 9814 9815 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9816 9817 The routine provides a copy of the Schur matrix stored within the solver data structures. 9818 The caller must destroy the object when it is no longer needed. 9819 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9820 9821 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) 9822 9823 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9824 9825 Developer Note: 9826 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9827 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9828 9829 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9830 @*/ 9831 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9832 { 9833 PetscFunctionBegin; 9834 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9835 if (S) PetscAssertPointer(S, 2); 9836 if (status) PetscAssertPointer(status, 3); 9837 if (S) { 9838 PetscErrorCode (*f)(Mat, Mat *); 9839 9840 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9841 if (f) { 9842 PetscCall((*f)(F, S)); 9843 } else { 9844 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9845 } 9846 } 9847 if (status) *status = F->schur_status; 9848 PetscFunctionReturn(PETSC_SUCCESS); 9849 } 9850 9851 /*@ 9852 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9853 9854 Logically Collective 9855 9856 Input Parameters: 9857 + F - the factored matrix obtained by calling `MatGetFactor()` 9858 . S - location where to return the Schur complement, can be `NULL` 9859 - status - the status of the Schur complement matrix, can be `NULL` 9860 9861 Level: advanced 9862 9863 Notes: 9864 You must call `MatFactorSetSchurIS()` before calling this routine. 9865 9866 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9867 9868 The routine returns a the Schur Complement stored within the data structures of the solver. 9869 9870 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9871 9872 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9873 9874 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9875 9876 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9877 9878 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9879 @*/ 9880 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9881 { 9882 PetscFunctionBegin; 9883 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9884 if (S) { 9885 PetscAssertPointer(S, 2); 9886 *S = F->schur; 9887 } 9888 if (status) { 9889 PetscAssertPointer(status, 3); 9890 *status = F->schur_status; 9891 } 9892 PetscFunctionReturn(PETSC_SUCCESS); 9893 } 9894 9895 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9896 { 9897 Mat S = F->schur; 9898 9899 PetscFunctionBegin; 9900 switch (F->schur_status) { 9901 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9902 case MAT_FACTOR_SCHUR_INVERTED: 9903 if (S) { 9904 S->ops->solve = NULL; 9905 S->ops->matsolve = NULL; 9906 S->ops->solvetranspose = NULL; 9907 S->ops->matsolvetranspose = NULL; 9908 S->ops->solveadd = NULL; 9909 S->ops->solvetransposeadd = NULL; 9910 S->factortype = MAT_FACTOR_NONE; 9911 PetscCall(PetscFree(S->solvertype)); 9912 } 9913 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9914 break; 9915 default: 9916 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9917 } 9918 PetscFunctionReturn(PETSC_SUCCESS); 9919 } 9920 9921 /*@ 9922 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9923 9924 Logically Collective 9925 9926 Input Parameters: 9927 + F - the factored matrix obtained by calling `MatGetFactor()` 9928 . S - location where the Schur complement is stored 9929 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9930 9931 Level: advanced 9932 9933 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9934 @*/ 9935 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9936 { 9937 PetscFunctionBegin; 9938 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9939 if (S) { 9940 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9941 *S = NULL; 9942 } 9943 F->schur_status = status; 9944 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9945 PetscFunctionReturn(PETSC_SUCCESS); 9946 } 9947 9948 /*@ 9949 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9950 9951 Logically Collective 9952 9953 Input Parameters: 9954 + F - the factored matrix obtained by calling `MatGetFactor()` 9955 . rhs - location where the right-hand side of the Schur complement system is stored 9956 - sol - location where the solution of the Schur complement system has to be returned 9957 9958 Level: advanced 9959 9960 Notes: 9961 The sizes of the vectors should match the size of the Schur complement 9962 9963 Must be called after `MatFactorSetSchurIS()` 9964 9965 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9966 @*/ 9967 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9968 { 9969 PetscFunctionBegin; 9970 PetscValidType(F, 1); 9971 PetscValidType(rhs, 2); 9972 PetscValidType(sol, 3); 9973 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9974 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9975 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9976 PetscCheckSameComm(F, 1, rhs, 2); 9977 PetscCheckSameComm(F, 1, sol, 3); 9978 PetscCall(MatFactorFactorizeSchurComplement(F)); 9979 switch (F->schur_status) { 9980 case MAT_FACTOR_SCHUR_FACTORED: 9981 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9982 break; 9983 case MAT_FACTOR_SCHUR_INVERTED: 9984 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9985 break; 9986 default: 9987 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9988 } 9989 PetscFunctionReturn(PETSC_SUCCESS); 9990 } 9991 9992 /*@ 9993 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9994 9995 Logically Collective 9996 9997 Input Parameters: 9998 + F - the factored matrix obtained by calling `MatGetFactor()` 9999 . rhs - location where the right-hand side of the Schur complement system is stored 10000 - sol - location where the solution of the Schur complement system has to be returned 10001 10002 Level: advanced 10003 10004 Notes: 10005 The sizes of the vectors should match the size of the Schur complement 10006 10007 Must be called after `MatFactorSetSchurIS()` 10008 10009 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10010 @*/ 10011 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10012 { 10013 PetscFunctionBegin; 10014 PetscValidType(F, 1); 10015 PetscValidType(rhs, 2); 10016 PetscValidType(sol, 3); 10017 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10018 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10019 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10020 PetscCheckSameComm(F, 1, rhs, 2); 10021 PetscCheckSameComm(F, 1, sol, 3); 10022 PetscCall(MatFactorFactorizeSchurComplement(F)); 10023 switch (F->schur_status) { 10024 case MAT_FACTOR_SCHUR_FACTORED: 10025 PetscCall(MatSolve(F->schur, rhs, sol)); 10026 break; 10027 case MAT_FACTOR_SCHUR_INVERTED: 10028 PetscCall(MatMult(F->schur, rhs, sol)); 10029 break; 10030 default: 10031 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10032 } 10033 PetscFunctionReturn(PETSC_SUCCESS); 10034 } 10035 10036 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10037 #if PetscDefined(HAVE_CUDA) 10038 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10039 #endif 10040 10041 /* Schur status updated in the interface */ 10042 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10043 { 10044 Mat S = F->schur; 10045 10046 PetscFunctionBegin; 10047 if (S) { 10048 PetscMPIInt size; 10049 PetscBool isdense, isdensecuda; 10050 10051 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10052 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10053 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10054 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10055 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10056 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10057 if (isdense) { 10058 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10059 } else if (isdensecuda) { 10060 #if defined(PETSC_HAVE_CUDA) 10061 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10062 #endif 10063 } 10064 // HIP?????????????? 10065 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10066 } 10067 PetscFunctionReturn(PETSC_SUCCESS); 10068 } 10069 10070 /*@ 10071 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10072 10073 Logically Collective 10074 10075 Input Parameter: 10076 . F - the factored matrix obtained by calling `MatGetFactor()` 10077 10078 Level: advanced 10079 10080 Notes: 10081 Must be called after `MatFactorSetSchurIS()`. 10082 10083 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10084 10085 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10086 @*/ 10087 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10088 { 10089 PetscFunctionBegin; 10090 PetscValidType(F, 1); 10091 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10092 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10093 PetscCall(MatFactorFactorizeSchurComplement(F)); 10094 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10095 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10096 PetscFunctionReturn(PETSC_SUCCESS); 10097 } 10098 10099 /*@ 10100 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10101 10102 Logically Collective 10103 10104 Input Parameter: 10105 . F - the factored matrix obtained by calling `MatGetFactor()` 10106 10107 Level: advanced 10108 10109 Note: 10110 Must be called after `MatFactorSetSchurIS()` 10111 10112 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10113 @*/ 10114 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10115 { 10116 MatFactorInfo info; 10117 10118 PetscFunctionBegin; 10119 PetscValidType(F, 1); 10120 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10121 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10122 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10123 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10124 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10125 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10126 } else { 10127 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10128 } 10129 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10130 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10131 PetscFunctionReturn(PETSC_SUCCESS); 10132 } 10133 10134 /*@ 10135 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10136 10137 Neighbor-wise Collective 10138 10139 Input Parameters: 10140 + A - the matrix 10141 . P - the projection matrix 10142 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10143 - 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 10144 if the result is a dense matrix this is irrelevant 10145 10146 Output Parameter: 10147 . C - the product matrix 10148 10149 Level: intermediate 10150 10151 Notes: 10152 C will be created and must be destroyed by the user with `MatDestroy()`. 10153 10154 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10155 10156 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10157 10158 Developer Note: 10159 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10160 10161 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10162 @*/ 10163 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10164 { 10165 PetscFunctionBegin; 10166 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10167 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10168 10169 if (scall == MAT_INITIAL_MATRIX) { 10170 PetscCall(MatProductCreate(A, P, NULL, C)); 10171 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10172 PetscCall(MatProductSetAlgorithm(*C, "default")); 10173 PetscCall(MatProductSetFill(*C, fill)); 10174 10175 (*C)->product->api_user = PETSC_TRUE; 10176 PetscCall(MatProductSetFromOptions(*C)); 10177 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); 10178 PetscCall(MatProductSymbolic(*C)); 10179 } else { /* scall == MAT_REUSE_MATRIX */ 10180 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10181 } 10182 10183 PetscCall(MatProductNumeric(*C)); 10184 (*C)->symmetric = A->symmetric; 10185 (*C)->spd = A->spd; 10186 PetscFunctionReturn(PETSC_SUCCESS); 10187 } 10188 10189 /*@ 10190 MatRARt - Creates the matrix product $C = R * A * R^T$ 10191 10192 Neighbor-wise Collective 10193 10194 Input Parameters: 10195 + A - the matrix 10196 . R - the projection matrix 10197 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10198 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10199 if the result is a dense matrix this is irrelevant 10200 10201 Output Parameter: 10202 . C - the product matrix 10203 10204 Level: intermediate 10205 10206 Notes: 10207 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10208 10209 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10210 10211 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10212 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10213 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10214 We recommend using `MatPtAP()` when possible. 10215 10216 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10217 10218 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10219 @*/ 10220 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10221 { 10222 PetscFunctionBegin; 10223 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10224 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10225 10226 if (scall == MAT_INITIAL_MATRIX) { 10227 PetscCall(MatProductCreate(A, R, NULL, C)); 10228 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10229 PetscCall(MatProductSetAlgorithm(*C, "default")); 10230 PetscCall(MatProductSetFill(*C, fill)); 10231 10232 (*C)->product->api_user = PETSC_TRUE; 10233 PetscCall(MatProductSetFromOptions(*C)); 10234 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); 10235 PetscCall(MatProductSymbolic(*C)); 10236 } else { /* scall == MAT_REUSE_MATRIX */ 10237 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10238 } 10239 10240 PetscCall(MatProductNumeric(*C)); 10241 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10242 PetscFunctionReturn(PETSC_SUCCESS); 10243 } 10244 10245 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10246 { 10247 PetscBool flg = PETSC_TRUE; 10248 10249 PetscFunctionBegin; 10250 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10251 if (scall == MAT_INITIAL_MATRIX) { 10252 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10253 PetscCall(MatProductCreate(A, B, NULL, C)); 10254 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10255 PetscCall(MatProductSetFill(*C, fill)); 10256 } else { /* scall == MAT_REUSE_MATRIX */ 10257 Mat_Product *product = (*C)->product; 10258 10259 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10260 if (flg && product && product->type != ptype) { 10261 PetscCall(MatProductClear(*C)); 10262 product = NULL; 10263 } 10264 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10265 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10266 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10267 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10268 product = (*C)->product; 10269 product->fill = fill; 10270 product->clear = PETSC_TRUE; 10271 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10272 flg = PETSC_FALSE; 10273 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10274 } 10275 } 10276 if (flg) { 10277 (*C)->product->api_user = PETSC_TRUE; 10278 PetscCall(MatProductSetType(*C, ptype)); 10279 PetscCall(MatProductSetFromOptions(*C)); 10280 PetscCall(MatProductSymbolic(*C)); 10281 } 10282 PetscCall(MatProductNumeric(*C)); 10283 PetscFunctionReturn(PETSC_SUCCESS); 10284 } 10285 10286 /*@ 10287 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10288 10289 Neighbor-wise Collective 10290 10291 Input Parameters: 10292 + A - the left matrix 10293 . B - the right matrix 10294 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10295 - 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 10296 if the result is a dense matrix this is irrelevant 10297 10298 Output Parameter: 10299 . C - the product matrix 10300 10301 Notes: 10302 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10303 10304 `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 10305 call to this function with `MAT_INITIAL_MATRIX`. 10306 10307 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10308 10309 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`, 10310 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10311 10312 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10313 10314 Example of Usage: 10315 .vb 10316 MatProductCreate(A,B,NULL,&C); 10317 MatProductSetType(C,MATPRODUCT_AB); 10318 MatProductSymbolic(C); 10319 MatProductNumeric(C); // compute C=A * B 10320 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10321 MatProductNumeric(C); 10322 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10323 MatProductNumeric(C); 10324 .ve 10325 10326 Level: intermediate 10327 10328 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10329 @*/ 10330 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10331 { 10332 PetscFunctionBegin; 10333 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10334 PetscFunctionReturn(PETSC_SUCCESS); 10335 } 10336 10337 /*@ 10338 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10339 10340 Neighbor-wise Collective 10341 10342 Input Parameters: 10343 + A - the left matrix 10344 . B - the right matrix 10345 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10346 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10347 10348 Output Parameter: 10349 . C - the product matrix 10350 10351 Options Database Key: 10352 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10353 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10354 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10355 10356 Level: intermediate 10357 10358 Notes: 10359 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10360 10361 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10362 10363 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10364 actually needed. 10365 10366 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10367 and for pairs of `MATMPIDENSE` matrices. 10368 10369 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10370 10371 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10372 10373 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10374 @*/ 10375 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10376 { 10377 PetscFunctionBegin; 10378 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10379 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10380 PetscFunctionReturn(PETSC_SUCCESS); 10381 } 10382 10383 /*@ 10384 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10385 10386 Neighbor-wise Collective 10387 10388 Input Parameters: 10389 + A - the left matrix 10390 . B - the right matrix 10391 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10392 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10393 10394 Output Parameter: 10395 . C - the product matrix 10396 10397 Level: intermediate 10398 10399 Notes: 10400 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10401 10402 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10403 10404 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10405 10406 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10407 actually needed. 10408 10409 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10410 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10411 10412 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10413 10414 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10415 @*/ 10416 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10417 { 10418 PetscFunctionBegin; 10419 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10420 PetscFunctionReturn(PETSC_SUCCESS); 10421 } 10422 10423 /*@ 10424 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10425 10426 Neighbor-wise Collective 10427 10428 Input Parameters: 10429 + A - the left matrix 10430 . B - the middle matrix 10431 . C - the right matrix 10432 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10433 - 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 10434 if the result is a dense matrix this is irrelevant 10435 10436 Output Parameter: 10437 . D - the product matrix 10438 10439 Level: intermediate 10440 10441 Notes: 10442 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10443 10444 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10445 10446 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10447 10448 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10449 actually needed. 10450 10451 If you have many matrices with the same non-zero structure to multiply, you 10452 should use `MAT_REUSE_MATRIX` in all calls but the first 10453 10454 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10455 10456 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10457 @*/ 10458 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10459 { 10460 PetscFunctionBegin; 10461 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10462 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10463 10464 if (scall == MAT_INITIAL_MATRIX) { 10465 PetscCall(MatProductCreate(A, B, C, D)); 10466 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10467 PetscCall(MatProductSetAlgorithm(*D, "default")); 10468 PetscCall(MatProductSetFill(*D, fill)); 10469 10470 (*D)->product->api_user = PETSC_TRUE; 10471 PetscCall(MatProductSetFromOptions(*D)); 10472 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, 10473 ((PetscObject)C)->type_name); 10474 PetscCall(MatProductSymbolic(*D)); 10475 } else { /* user may change input matrices when REUSE */ 10476 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10477 } 10478 PetscCall(MatProductNumeric(*D)); 10479 PetscFunctionReturn(PETSC_SUCCESS); 10480 } 10481 10482 /*@ 10483 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10484 10485 Collective 10486 10487 Input Parameters: 10488 + mat - the matrix 10489 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10490 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10491 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10492 10493 Output Parameter: 10494 . matredundant - redundant matrix 10495 10496 Level: advanced 10497 10498 Notes: 10499 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10500 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10501 10502 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10503 calling it. 10504 10505 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10506 10507 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10508 @*/ 10509 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10510 { 10511 MPI_Comm comm; 10512 PetscMPIInt size; 10513 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10514 Mat_Redundant *redund = NULL; 10515 PetscSubcomm psubcomm = NULL; 10516 MPI_Comm subcomm_in = subcomm; 10517 Mat *matseq; 10518 IS isrow, iscol; 10519 PetscBool newsubcomm = PETSC_FALSE; 10520 10521 PetscFunctionBegin; 10522 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10523 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10524 PetscAssertPointer(*matredundant, 5); 10525 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10526 } 10527 10528 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10529 if (size == 1 || nsubcomm == 1) { 10530 if (reuse == MAT_INITIAL_MATRIX) { 10531 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10532 } else { 10533 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"); 10534 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10535 } 10536 PetscFunctionReturn(PETSC_SUCCESS); 10537 } 10538 10539 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10540 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10541 MatCheckPreallocated(mat, 1); 10542 10543 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10544 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10545 /* create psubcomm, then get subcomm */ 10546 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10547 PetscCallMPI(MPI_Comm_size(comm, &size)); 10548 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10549 10550 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10551 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10552 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10553 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10554 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10555 newsubcomm = PETSC_TRUE; 10556 PetscCall(PetscSubcommDestroy(&psubcomm)); 10557 } 10558 10559 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10560 if (reuse == MAT_INITIAL_MATRIX) { 10561 mloc_sub = PETSC_DECIDE; 10562 nloc_sub = PETSC_DECIDE; 10563 if (bs < 1) { 10564 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10565 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10566 } else { 10567 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10568 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10569 } 10570 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10571 rstart = rend - mloc_sub; 10572 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10573 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10574 PetscCall(ISSetIdentity(iscol)); 10575 } else { /* reuse == MAT_REUSE_MATRIX */ 10576 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"); 10577 /* retrieve subcomm */ 10578 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10579 redund = (*matredundant)->redundant; 10580 isrow = redund->isrow; 10581 iscol = redund->iscol; 10582 matseq = redund->matseq; 10583 } 10584 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10585 10586 /* get matredundant over subcomm */ 10587 if (reuse == MAT_INITIAL_MATRIX) { 10588 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10589 10590 /* create a supporting struct and attach it to C for reuse */ 10591 PetscCall(PetscNew(&redund)); 10592 (*matredundant)->redundant = redund; 10593 redund->isrow = isrow; 10594 redund->iscol = iscol; 10595 redund->matseq = matseq; 10596 if (newsubcomm) { 10597 redund->subcomm = subcomm; 10598 } else { 10599 redund->subcomm = MPI_COMM_NULL; 10600 } 10601 } else { 10602 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10603 } 10604 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10605 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10606 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10607 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10608 } 10609 #endif 10610 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10611 PetscFunctionReturn(PETSC_SUCCESS); 10612 } 10613 10614 /*@C 10615 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10616 a given `Mat`. Each submatrix can span multiple procs. 10617 10618 Collective 10619 10620 Input Parameters: 10621 + mat - the matrix 10622 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10623 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10624 10625 Output Parameter: 10626 . subMat - parallel sub-matrices each spanning a given `subcomm` 10627 10628 Level: advanced 10629 10630 Notes: 10631 The submatrix partition across processors is dictated by `subComm` a 10632 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10633 is not restricted to be grouped with consecutive original MPI processes. 10634 10635 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10636 map directly to the layout of the original matrix [wrt the local 10637 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10638 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10639 the `subMat`. However the offDiagMat looses some columns - and this is 10640 reconstructed with `MatSetValues()` 10641 10642 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10643 10644 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10645 @*/ 10646 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10647 { 10648 PetscMPIInt commsize, subCommSize; 10649 10650 PetscFunctionBegin; 10651 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10652 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10653 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10654 10655 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"); 10656 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10657 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10658 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10659 PetscFunctionReturn(PETSC_SUCCESS); 10660 } 10661 10662 /*@ 10663 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10664 10665 Not Collective 10666 10667 Input Parameters: 10668 + mat - matrix to extract local submatrix from 10669 . isrow - local row indices for submatrix 10670 - iscol - local column indices for submatrix 10671 10672 Output Parameter: 10673 . submat - the submatrix 10674 10675 Level: intermediate 10676 10677 Notes: 10678 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10679 10680 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10681 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10682 10683 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10684 `MatSetValuesBlockedLocal()` will also be implemented. 10685 10686 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10687 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10688 10689 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10690 @*/ 10691 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10692 { 10693 PetscFunctionBegin; 10694 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10695 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10696 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10697 PetscCheckSameComm(isrow, 2, iscol, 3); 10698 PetscAssertPointer(submat, 4); 10699 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10700 10701 if (mat->ops->getlocalsubmatrix) { 10702 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10703 } else { 10704 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10705 } 10706 PetscFunctionReturn(PETSC_SUCCESS); 10707 } 10708 10709 /*@ 10710 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10711 10712 Not Collective 10713 10714 Input Parameters: 10715 + mat - matrix to extract local submatrix from 10716 . isrow - local row indices for submatrix 10717 . iscol - local column indices for submatrix 10718 - submat - the submatrix 10719 10720 Level: intermediate 10721 10722 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10723 @*/ 10724 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10725 { 10726 PetscFunctionBegin; 10727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10728 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10729 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10730 PetscCheckSameComm(isrow, 2, iscol, 3); 10731 PetscAssertPointer(submat, 4); 10732 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10733 10734 if (mat->ops->restorelocalsubmatrix) { 10735 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10736 } else { 10737 PetscCall(MatDestroy(submat)); 10738 } 10739 *submat = NULL; 10740 PetscFunctionReturn(PETSC_SUCCESS); 10741 } 10742 10743 /*@ 10744 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10745 10746 Collective 10747 10748 Input Parameter: 10749 . mat - the matrix 10750 10751 Output Parameter: 10752 . is - if any rows have zero diagonals this contains the list of them 10753 10754 Level: developer 10755 10756 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10757 @*/ 10758 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10759 { 10760 PetscFunctionBegin; 10761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10762 PetscValidType(mat, 1); 10763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10765 10766 if (!mat->ops->findzerodiagonals) { 10767 Vec diag; 10768 const PetscScalar *a; 10769 PetscInt *rows; 10770 PetscInt rStart, rEnd, r, nrow = 0; 10771 10772 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10773 PetscCall(MatGetDiagonal(mat, diag)); 10774 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10775 PetscCall(VecGetArrayRead(diag, &a)); 10776 for (r = 0; r < rEnd - rStart; ++r) 10777 if (a[r] == 0.0) ++nrow; 10778 PetscCall(PetscMalloc1(nrow, &rows)); 10779 nrow = 0; 10780 for (r = 0; r < rEnd - rStart; ++r) 10781 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10782 PetscCall(VecRestoreArrayRead(diag, &a)); 10783 PetscCall(VecDestroy(&diag)); 10784 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10785 } else { 10786 PetscUseTypeMethod(mat, findzerodiagonals, is); 10787 } 10788 PetscFunctionReturn(PETSC_SUCCESS); 10789 } 10790 10791 /*@ 10792 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10793 10794 Collective 10795 10796 Input Parameter: 10797 . mat - the matrix 10798 10799 Output Parameter: 10800 . is - contains the list of rows with off block diagonal entries 10801 10802 Level: developer 10803 10804 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10805 @*/ 10806 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10807 { 10808 PetscFunctionBegin; 10809 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10810 PetscValidType(mat, 1); 10811 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10812 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10813 10814 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10815 PetscFunctionReturn(PETSC_SUCCESS); 10816 } 10817 10818 /*@C 10819 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10820 10821 Collective; No Fortran Support 10822 10823 Input Parameter: 10824 . mat - the matrix 10825 10826 Output Parameter: 10827 . values - the block inverses in column major order (FORTRAN-like) 10828 10829 Level: advanced 10830 10831 Notes: 10832 The size of the blocks is determined by the block size of the matrix. 10833 10834 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10835 10836 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10837 10838 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10839 @*/ 10840 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10841 { 10842 PetscFunctionBegin; 10843 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10844 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10845 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10846 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10847 PetscFunctionReturn(PETSC_SUCCESS); 10848 } 10849 10850 /*@ 10851 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10852 10853 Collective; No Fortran Support 10854 10855 Input Parameters: 10856 + mat - the matrix 10857 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10858 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10859 10860 Output Parameter: 10861 . values - the block inverses in column major order (FORTRAN-like) 10862 10863 Level: advanced 10864 10865 Notes: 10866 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10867 10868 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10869 10870 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10871 @*/ 10872 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10873 { 10874 PetscFunctionBegin; 10875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10876 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10877 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10878 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10879 PetscFunctionReturn(PETSC_SUCCESS); 10880 } 10881 10882 /*@ 10883 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10884 10885 Collective 10886 10887 Input Parameters: 10888 + A - the matrix 10889 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10890 10891 Level: advanced 10892 10893 Note: 10894 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10895 10896 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10897 @*/ 10898 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10899 { 10900 const PetscScalar *vals; 10901 PetscInt *dnnz; 10902 PetscInt m, rstart, rend, bs, i, j; 10903 10904 PetscFunctionBegin; 10905 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10906 PetscCall(MatGetBlockSize(A, &bs)); 10907 PetscCall(MatGetLocalSize(A, &m, NULL)); 10908 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10909 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10910 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10911 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10912 PetscCall(PetscFree(dnnz)); 10913 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10914 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10915 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10916 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10917 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10918 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10919 PetscFunctionReturn(PETSC_SUCCESS); 10920 } 10921 10922 /*@ 10923 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10924 via `MatTransposeColoringCreate()`. 10925 10926 Collective 10927 10928 Input Parameter: 10929 . c - coloring context 10930 10931 Level: intermediate 10932 10933 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10934 @*/ 10935 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10936 { 10937 MatTransposeColoring matcolor = *c; 10938 10939 PetscFunctionBegin; 10940 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10941 if (--((PetscObject)matcolor)->refct > 0) { 10942 matcolor = NULL; 10943 PetscFunctionReturn(PETSC_SUCCESS); 10944 } 10945 10946 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10947 PetscCall(PetscFree(matcolor->rows)); 10948 PetscCall(PetscFree(matcolor->den2sp)); 10949 PetscCall(PetscFree(matcolor->colorforcol)); 10950 PetscCall(PetscFree(matcolor->columns)); 10951 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10952 PetscCall(PetscHeaderDestroy(c)); 10953 PetscFunctionReturn(PETSC_SUCCESS); 10954 } 10955 10956 /*@ 10957 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10958 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10959 `MatTransposeColoring` to sparse `B`. 10960 10961 Collective 10962 10963 Input Parameters: 10964 + coloring - coloring context created with `MatTransposeColoringCreate()` 10965 - B - sparse matrix 10966 10967 Output Parameter: 10968 . Btdense - dense matrix $B^T$ 10969 10970 Level: developer 10971 10972 Note: 10973 These are used internally for some implementations of `MatRARt()` 10974 10975 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10976 @*/ 10977 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10978 { 10979 PetscFunctionBegin; 10980 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10981 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10982 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10983 10984 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10985 PetscFunctionReturn(PETSC_SUCCESS); 10986 } 10987 10988 /*@ 10989 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10990 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10991 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10992 $C_{sp}$ from $C_{den}$. 10993 10994 Collective 10995 10996 Input Parameters: 10997 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10998 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10999 11000 Output Parameter: 11001 . Csp - sparse matrix 11002 11003 Level: developer 11004 11005 Note: 11006 These are used internally for some implementations of `MatRARt()` 11007 11008 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11009 @*/ 11010 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11011 { 11012 PetscFunctionBegin; 11013 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11014 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11015 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11016 11017 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11018 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11019 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11020 PetscFunctionReturn(PETSC_SUCCESS); 11021 } 11022 11023 /*@ 11024 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11025 11026 Collective 11027 11028 Input Parameters: 11029 + mat - the matrix product C 11030 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11031 11032 Output Parameter: 11033 . color - the new coloring context 11034 11035 Level: intermediate 11036 11037 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11038 `MatTransColoringApplyDenToSp()` 11039 @*/ 11040 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11041 { 11042 MatTransposeColoring c; 11043 MPI_Comm comm; 11044 11045 PetscFunctionBegin; 11046 PetscAssertPointer(color, 3); 11047 11048 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11049 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11050 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11051 c->ctype = iscoloring->ctype; 11052 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11053 *color = c; 11054 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11055 PetscFunctionReturn(PETSC_SUCCESS); 11056 } 11057 11058 /*@ 11059 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11060 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11061 11062 Not Collective 11063 11064 Input Parameter: 11065 . mat - the matrix 11066 11067 Output Parameter: 11068 . state - the current state 11069 11070 Level: intermediate 11071 11072 Notes: 11073 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11074 different matrices 11075 11076 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11077 11078 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11079 11080 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11081 @*/ 11082 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11083 { 11084 PetscFunctionBegin; 11085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11086 *state = mat->nonzerostate; 11087 PetscFunctionReturn(PETSC_SUCCESS); 11088 } 11089 11090 /*@ 11091 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11092 matrices from each processor 11093 11094 Collective 11095 11096 Input Parameters: 11097 + comm - the communicators the parallel matrix will live on 11098 . seqmat - the input sequential matrices 11099 . n - number of local columns (or `PETSC_DECIDE`) 11100 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11101 11102 Output Parameter: 11103 . mpimat - the parallel matrix generated 11104 11105 Level: developer 11106 11107 Note: 11108 The number of columns of the matrix in EACH processor MUST be the same. 11109 11110 .seealso: [](ch_matrices), `Mat` 11111 @*/ 11112 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11113 { 11114 PetscMPIInt size; 11115 11116 PetscFunctionBegin; 11117 PetscCallMPI(MPI_Comm_size(comm, &size)); 11118 if (size == 1) { 11119 if (reuse == MAT_INITIAL_MATRIX) { 11120 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11121 } else { 11122 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11123 } 11124 PetscFunctionReturn(PETSC_SUCCESS); 11125 } 11126 11127 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"); 11128 11129 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11130 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11131 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11132 PetscFunctionReturn(PETSC_SUCCESS); 11133 } 11134 11135 /*@ 11136 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11137 11138 Collective 11139 11140 Input Parameters: 11141 + A - the matrix to create subdomains from 11142 - N - requested number of subdomains 11143 11144 Output Parameters: 11145 + n - number of subdomains resulting on this MPI process 11146 - iss - `IS` list with indices of subdomains on this MPI process 11147 11148 Level: advanced 11149 11150 Note: 11151 The number of subdomains must be smaller than the communicator size 11152 11153 .seealso: [](ch_matrices), `Mat`, `IS` 11154 @*/ 11155 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11156 { 11157 MPI_Comm comm, subcomm; 11158 PetscMPIInt size, rank, color; 11159 PetscInt rstart, rend, k; 11160 11161 PetscFunctionBegin; 11162 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11163 PetscCallMPI(MPI_Comm_size(comm, &size)); 11164 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11165 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); 11166 *n = 1; 11167 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11168 color = rank / k; 11169 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11170 PetscCall(PetscMalloc1(1, iss)); 11171 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11172 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11173 PetscCallMPI(MPI_Comm_free(&subcomm)); 11174 PetscFunctionReturn(PETSC_SUCCESS); 11175 } 11176 11177 /*@ 11178 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11179 11180 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11181 If they are not the same, uses `MatMatMatMult()`. 11182 11183 Once the coarse grid problem is constructed, correct for interpolation operators 11184 that are not of full rank, which can legitimately happen in the case of non-nested 11185 geometric multigrid. 11186 11187 Input Parameters: 11188 + restrct - restriction operator 11189 . dA - fine grid matrix 11190 . interpolate - interpolation operator 11191 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11192 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11193 11194 Output Parameter: 11195 . A - the Galerkin coarse matrix 11196 11197 Options Database Key: 11198 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11199 11200 Level: developer 11201 11202 Note: 11203 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11204 11205 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11206 @*/ 11207 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11208 { 11209 IS zerorows; 11210 Vec diag; 11211 11212 PetscFunctionBegin; 11213 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11214 /* Construct the coarse grid matrix */ 11215 if (interpolate == restrct) { 11216 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11217 } else { 11218 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11219 } 11220 11221 /* If the interpolation matrix is not of full rank, A will have zero rows. 11222 This can legitimately happen in the case of non-nested geometric multigrid. 11223 In that event, we set the rows of the matrix to the rows of the identity, 11224 ignoring the equations (as the RHS will also be zero). */ 11225 11226 PetscCall(MatFindZeroRows(*A, &zerorows)); 11227 11228 if (zerorows != NULL) { /* if there are any zero rows */ 11229 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11230 PetscCall(MatGetDiagonal(*A, diag)); 11231 PetscCall(VecISSet(diag, zerorows, 1.0)); 11232 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11233 PetscCall(VecDestroy(&diag)); 11234 PetscCall(ISDestroy(&zerorows)); 11235 } 11236 PetscFunctionReturn(PETSC_SUCCESS); 11237 } 11238 11239 /*@C 11240 MatSetOperation - Allows user to set a matrix operation for any matrix type 11241 11242 Logically Collective 11243 11244 Input Parameters: 11245 + mat - the matrix 11246 . op - the name of the operation 11247 - f - the function that provides the operation 11248 11249 Level: developer 11250 11251 Example Usage: 11252 .vb 11253 extern PetscErrorCode usermult(Mat, Vec, Vec); 11254 11255 PetscCall(MatCreateXXX(comm, ..., &A)); 11256 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11257 .ve 11258 11259 Notes: 11260 See the file `include/petscmat.h` for a complete list of matrix 11261 operations, which all have the form MATOP_<OPERATION>, where 11262 <OPERATION> is the name (in all capital letters) of the 11263 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11264 11265 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11266 sequence as the usual matrix interface routines, since they 11267 are intended to be accessed via the usual matrix interface 11268 routines, e.g., 11269 .vb 11270 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11271 .ve 11272 11273 In particular each function MUST return `PETSC_SUCCESS` on success and 11274 nonzero on failure. 11275 11276 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11277 11278 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11279 @*/ 11280 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11281 { 11282 PetscFunctionBegin; 11283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11284 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11285 (((void (**)(void))mat->ops)[op]) = f; 11286 PetscFunctionReturn(PETSC_SUCCESS); 11287 } 11288 11289 /*@C 11290 MatGetOperation - Gets a matrix operation for any matrix type. 11291 11292 Not Collective 11293 11294 Input Parameters: 11295 + mat - the matrix 11296 - op - the name of the operation 11297 11298 Output Parameter: 11299 . f - the function that provides the operation 11300 11301 Level: developer 11302 11303 Example Usage: 11304 .vb 11305 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11306 11307 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11308 .ve 11309 11310 Notes: 11311 See the file include/petscmat.h for a complete list of matrix 11312 operations, which all have the form MATOP_<OPERATION>, where 11313 <OPERATION> is the name (in all capital letters) of the 11314 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11315 11316 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11317 11318 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11319 @*/ 11320 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11321 { 11322 PetscFunctionBegin; 11323 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11324 *f = (((void (**)(void))mat->ops)[op]); 11325 PetscFunctionReturn(PETSC_SUCCESS); 11326 } 11327 11328 /*@ 11329 MatHasOperation - Determines whether the given matrix supports the particular operation. 11330 11331 Not Collective 11332 11333 Input Parameters: 11334 + mat - the matrix 11335 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11336 11337 Output Parameter: 11338 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11339 11340 Level: advanced 11341 11342 Note: 11343 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11344 11345 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11346 @*/ 11347 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11348 { 11349 PetscFunctionBegin; 11350 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11351 PetscAssertPointer(has, 3); 11352 if (mat->ops->hasoperation) { 11353 PetscUseTypeMethod(mat, hasoperation, op, has); 11354 } else { 11355 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11356 else { 11357 *has = PETSC_FALSE; 11358 if (op == MATOP_CREATE_SUBMATRIX) { 11359 PetscMPIInt size; 11360 11361 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11362 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11363 } 11364 } 11365 } 11366 PetscFunctionReturn(PETSC_SUCCESS); 11367 } 11368 11369 /*@ 11370 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11371 11372 Collective 11373 11374 Input Parameter: 11375 . mat - the matrix 11376 11377 Output Parameter: 11378 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11379 11380 Level: beginner 11381 11382 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11383 @*/ 11384 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11385 { 11386 PetscFunctionBegin; 11387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11388 PetscValidType(mat, 1); 11389 PetscAssertPointer(cong, 2); 11390 if (!mat->rmap || !mat->cmap) { 11391 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11392 PetscFunctionReturn(PETSC_SUCCESS); 11393 } 11394 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11395 PetscCall(PetscLayoutSetUp(mat->rmap)); 11396 PetscCall(PetscLayoutSetUp(mat->cmap)); 11397 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11398 if (*cong) mat->congruentlayouts = 1; 11399 else mat->congruentlayouts = 0; 11400 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11401 PetscFunctionReturn(PETSC_SUCCESS); 11402 } 11403 11404 PetscErrorCode MatSetInf(Mat A) 11405 { 11406 PetscFunctionBegin; 11407 PetscUseTypeMethod(A, setinf); 11408 PetscFunctionReturn(PETSC_SUCCESS); 11409 } 11410 11411 /*@ 11412 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 11413 and possibly removes small values from the graph structure. 11414 11415 Collective 11416 11417 Input Parameters: 11418 + A - the matrix 11419 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11420 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11421 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11422 . num_idx - size of 'index' array 11423 - index - array of block indices to use for graph strength of connection weight 11424 11425 Output Parameter: 11426 . graph - the resulting graph 11427 11428 Level: advanced 11429 11430 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11431 @*/ 11432 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11433 { 11434 PetscFunctionBegin; 11435 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11436 PetscValidType(A, 1); 11437 PetscValidLogicalCollectiveBool(A, scale, 3); 11438 PetscAssertPointer(graph, 7); 11439 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11440 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11441 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11442 PetscFunctionReturn(PETSC_SUCCESS); 11443 } 11444 11445 /*@ 11446 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11447 meaning the same memory is used for the matrix, and no new memory is allocated. 11448 11449 Collective 11450 11451 Input Parameters: 11452 + A - the matrix 11453 - 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 11454 11455 Level: intermediate 11456 11457 Developer Note: 11458 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11459 of the arrays in the data structure are unneeded. 11460 11461 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11462 @*/ 11463 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11464 { 11465 PetscFunctionBegin; 11466 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11467 PetscUseTypeMethod(A, eliminatezeros, keep); 11468 PetscFunctionReturn(PETSC_SUCCESS); 11469 } 11470