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 .seealso: [](ch_matrices), `Mat` 5619 @*/ 5620 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5621 { 5622 PetscFunctionBegin; 5623 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5624 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5625 PetscValidType(A, 1); 5626 PetscValidType(B, 2); 5627 PetscAssertPointer(flg, 3); 5628 PetscCheckSameComm(A, 1, B, 2); 5629 MatCheckPreallocated(A, 1); 5630 MatCheckPreallocated(B, 2); 5631 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5632 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5633 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, 5634 B->cmap->N); 5635 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5636 PetscUseTypeMethod(A, equal, B, flg); 5637 } else { 5638 PetscCall(MatMultEqual(A, B, 10, flg)); 5639 } 5640 PetscFunctionReturn(PETSC_SUCCESS); 5641 } 5642 5643 /*@ 5644 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5645 matrices that are stored as vectors. Either of the two scaling 5646 matrices can be `NULL`. 5647 5648 Collective 5649 5650 Input Parameters: 5651 + mat - the matrix to be scaled 5652 . l - the left scaling vector (or `NULL`) 5653 - r - the right scaling vector (or `NULL`) 5654 5655 Level: intermediate 5656 5657 Note: 5658 `MatDiagonalScale()` computes $A = LAR$, where 5659 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5660 The L scales the rows of the matrix, the R scales the columns of the matrix. 5661 5662 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5663 @*/ 5664 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5665 { 5666 PetscFunctionBegin; 5667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5668 PetscValidType(mat, 1); 5669 if (l) { 5670 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5671 PetscCheckSameComm(mat, 1, l, 2); 5672 } 5673 if (r) { 5674 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5675 PetscCheckSameComm(mat, 1, r, 3); 5676 } 5677 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5678 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5679 MatCheckPreallocated(mat, 1); 5680 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5681 5682 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5683 PetscUseTypeMethod(mat, diagonalscale, l, r); 5684 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5685 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5686 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5687 PetscFunctionReturn(PETSC_SUCCESS); 5688 } 5689 5690 /*@ 5691 MatScale - Scales all elements of a matrix by a given number. 5692 5693 Logically Collective 5694 5695 Input Parameters: 5696 + mat - the matrix to be scaled 5697 - a - the scaling value 5698 5699 Level: intermediate 5700 5701 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5702 @*/ 5703 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5704 { 5705 PetscFunctionBegin; 5706 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5707 PetscValidType(mat, 1); 5708 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5709 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5710 PetscValidLogicalCollectiveScalar(mat, a, 2); 5711 MatCheckPreallocated(mat, 1); 5712 5713 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5714 if (a != (PetscScalar)1.0) { 5715 PetscUseTypeMethod(mat, scale, a); 5716 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5717 } 5718 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5719 PetscFunctionReturn(PETSC_SUCCESS); 5720 } 5721 5722 /*@ 5723 MatNorm - Calculates various norms of a matrix. 5724 5725 Collective 5726 5727 Input Parameters: 5728 + mat - the matrix 5729 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5730 5731 Output Parameter: 5732 . nrm - the resulting norm 5733 5734 Level: intermediate 5735 5736 .seealso: [](ch_matrices), `Mat` 5737 @*/ 5738 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5739 { 5740 PetscFunctionBegin; 5741 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5742 PetscValidType(mat, 1); 5743 PetscAssertPointer(nrm, 3); 5744 5745 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5746 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5747 MatCheckPreallocated(mat, 1); 5748 5749 PetscUseTypeMethod(mat, norm, type, nrm); 5750 PetscFunctionReturn(PETSC_SUCCESS); 5751 } 5752 5753 /* 5754 This variable is used to prevent counting of MatAssemblyBegin() that 5755 are called from within a MatAssemblyEnd(). 5756 */ 5757 static PetscInt MatAssemblyEnd_InUse = 0; 5758 /*@ 5759 MatAssemblyBegin - Begins assembling the matrix. This routine should 5760 be called after completing all calls to `MatSetValues()`. 5761 5762 Collective 5763 5764 Input Parameters: 5765 + mat - the matrix 5766 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5767 5768 Level: beginner 5769 5770 Notes: 5771 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5772 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5773 5774 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5775 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5776 using the matrix. 5777 5778 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5779 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 5780 a global collective operation requiring all processes that share the matrix. 5781 5782 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5783 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5784 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5785 5786 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5787 @*/ 5788 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5789 { 5790 PetscFunctionBegin; 5791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5792 PetscValidType(mat, 1); 5793 MatCheckPreallocated(mat, 1); 5794 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5795 if (mat->assembled) { 5796 mat->was_assembled = PETSC_TRUE; 5797 mat->assembled = PETSC_FALSE; 5798 } 5799 5800 if (!MatAssemblyEnd_InUse) { 5801 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5802 PetscTryTypeMethod(mat, assemblybegin, type); 5803 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5804 } else PetscTryTypeMethod(mat, assemblybegin, type); 5805 PetscFunctionReturn(PETSC_SUCCESS); 5806 } 5807 5808 /*@ 5809 MatAssembled - Indicates if a matrix has been assembled and is ready for 5810 use; for example, in matrix-vector product. 5811 5812 Not Collective 5813 5814 Input Parameter: 5815 . mat - the matrix 5816 5817 Output Parameter: 5818 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5819 5820 Level: advanced 5821 5822 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5823 @*/ 5824 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5825 { 5826 PetscFunctionBegin; 5827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5828 PetscAssertPointer(assembled, 2); 5829 *assembled = mat->assembled; 5830 PetscFunctionReturn(PETSC_SUCCESS); 5831 } 5832 5833 /*@ 5834 MatAssemblyEnd - Completes assembling the matrix. This routine should 5835 be called after `MatAssemblyBegin()`. 5836 5837 Collective 5838 5839 Input Parameters: 5840 + mat - the matrix 5841 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5842 5843 Options Database Keys: 5844 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5845 . -mat_view ::ascii_info_detail - Prints more detailed info 5846 . -mat_view - Prints matrix in ASCII format 5847 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5848 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5849 . -display <name> - Sets display name (default is host) 5850 . -draw_pause <sec> - Sets number of seconds to pause after display 5851 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5852 . -viewer_socket_machine <machine> - Machine to use for socket 5853 . -viewer_socket_port <port> - Port number to use for socket 5854 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5855 5856 Level: beginner 5857 5858 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5859 @*/ 5860 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5861 { 5862 static PetscInt inassm = 0; 5863 PetscBool flg = PETSC_FALSE; 5864 5865 PetscFunctionBegin; 5866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5867 PetscValidType(mat, 1); 5868 5869 inassm++; 5870 MatAssemblyEnd_InUse++; 5871 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5872 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5873 PetscTryTypeMethod(mat, assemblyend, type); 5874 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5875 } else PetscTryTypeMethod(mat, assemblyend, type); 5876 5877 /* Flush assembly is not a true assembly */ 5878 if (type != MAT_FLUSH_ASSEMBLY) { 5879 if (mat->num_ass) { 5880 if (!mat->symmetry_eternal) { 5881 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5882 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5883 } 5884 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5885 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5886 } 5887 mat->num_ass++; 5888 mat->assembled = PETSC_TRUE; 5889 mat->ass_nonzerostate = mat->nonzerostate; 5890 } 5891 5892 mat->insertmode = NOT_SET_VALUES; 5893 MatAssemblyEnd_InUse--; 5894 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5895 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5896 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5897 5898 if (mat->checksymmetryonassembly) { 5899 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5900 if (flg) { 5901 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5902 } else { 5903 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5904 } 5905 } 5906 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5907 } 5908 inassm--; 5909 PetscFunctionReturn(PETSC_SUCCESS); 5910 } 5911 5912 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5913 /*@ 5914 MatSetOption - Sets a parameter option for a matrix. Some options 5915 may be specific to certain storage formats. Some options 5916 determine how values will be inserted (or added). Sorted, 5917 row-oriented input will generally assemble the fastest. The default 5918 is row-oriented. 5919 5920 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5921 5922 Input Parameters: 5923 + mat - the matrix 5924 . op - the option, one of those listed below (and possibly others), 5925 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5926 5927 Options Describing Matrix Structure: 5928 + `MAT_SPD` - symmetric positive definite 5929 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5930 . `MAT_HERMITIAN` - transpose is the complex conjugation 5931 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5932 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5933 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5934 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5935 5936 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5937 do not need to be computed (usually at a high cost) 5938 5939 Options For Use with `MatSetValues()`: 5940 Insert a logically dense subblock, which can be 5941 . `MAT_ROW_ORIENTED` - row-oriented (default) 5942 5943 These options reflect the data you pass in with `MatSetValues()`; it has 5944 nothing to do with how the data is stored internally in the matrix 5945 data structure. 5946 5947 When (re)assembling a matrix, we can restrict the input for 5948 efficiency/debugging purposes. These options include 5949 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5950 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5951 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5952 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5953 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5954 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5955 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5956 performance for very large process counts. 5957 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5958 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5959 functions, instead sending only neighbor messages. 5960 5961 Level: intermediate 5962 5963 Notes: 5964 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5965 5966 Some options are relevant only for particular matrix types and 5967 are thus ignored by others. Other options are not supported by 5968 certain matrix types and will generate an error message if set. 5969 5970 If using Fortran to compute a matrix, one may need to 5971 use the column-oriented option (or convert to the row-oriented 5972 format). 5973 5974 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5975 that would generate a new entry in the nonzero structure is instead 5976 ignored. Thus, if memory has not already been allocated for this particular 5977 data, then the insertion is ignored. For dense matrices, in which 5978 the entire array is allocated, no entries are ever ignored. 5979 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5980 5981 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5982 that would generate a new entry in the nonzero structure instead produces 5983 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 5984 5985 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5986 that would generate a new entry that has not been preallocated will 5987 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5988 only.) This is a useful flag when debugging matrix memory preallocation. 5989 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5990 5991 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5992 other processors should be dropped, rather than stashed. 5993 This is useful if you know that the "owning" processor is also 5994 always generating the correct matrix entries, so that PETSc need 5995 not transfer duplicate entries generated on another processor. 5996 5997 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5998 searches during matrix assembly. When this flag is set, the hash table 5999 is created during the first matrix assembly. This hash table is 6000 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6001 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6002 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6003 supported by `MATMPIBAIJ` format only. 6004 6005 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6006 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6007 6008 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6009 a zero location in the matrix 6010 6011 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6012 6013 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6014 zero row routines and thus improves performance for very large process counts. 6015 6016 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6017 part of the matrix (since they should match the upper triangular part). 6018 6019 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6020 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6021 with finite difference schemes with non-periodic boundary conditions. 6022 6023 Developer Note: 6024 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6025 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6026 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6027 not changed. 6028 6029 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6030 @*/ 6031 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6032 { 6033 PetscFunctionBegin; 6034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6035 if (op > 0) { 6036 PetscValidLogicalCollectiveEnum(mat, op, 2); 6037 PetscValidLogicalCollectiveBool(mat, flg, 3); 6038 } 6039 6040 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); 6041 6042 switch (op) { 6043 case MAT_FORCE_DIAGONAL_ENTRIES: 6044 mat->force_diagonals = flg; 6045 PetscFunctionReturn(PETSC_SUCCESS); 6046 case MAT_NO_OFF_PROC_ENTRIES: 6047 mat->nooffprocentries = flg; 6048 PetscFunctionReturn(PETSC_SUCCESS); 6049 case MAT_SUBSET_OFF_PROC_ENTRIES: 6050 mat->assembly_subset = flg; 6051 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6052 #if !defined(PETSC_HAVE_MPIUNI) 6053 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6054 #endif 6055 mat->stash.first_assembly_done = PETSC_FALSE; 6056 } 6057 PetscFunctionReturn(PETSC_SUCCESS); 6058 case MAT_NO_OFF_PROC_ZERO_ROWS: 6059 mat->nooffproczerorows = flg; 6060 PetscFunctionReturn(PETSC_SUCCESS); 6061 case MAT_SPD: 6062 if (flg) { 6063 mat->spd = PETSC_BOOL3_TRUE; 6064 mat->symmetric = PETSC_BOOL3_TRUE; 6065 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6066 } else { 6067 mat->spd = PETSC_BOOL3_FALSE; 6068 } 6069 break; 6070 case MAT_SYMMETRIC: 6071 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6072 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6073 #if !defined(PETSC_USE_COMPLEX) 6074 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6075 #endif 6076 break; 6077 case MAT_HERMITIAN: 6078 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6079 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6080 #if !defined(PETSC_USE_COMPLEX) 6081 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6082 #endif 6083 break; 6084 case MAT_STRUCTURALLY_SYMMETRIC: 6085 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6086 break; 6087 case MAT_SYMMETRY_ETERNAL: 6088 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"); 6089 mat->symmetry_eternal = flg; 6090 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6091 break; 6092 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6093 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"); 6094 mat->structural_symmetry_eternal = flg; 6095 break; 6096 case MAT_SPD_ETERNAL: 6097 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"); 6098 mat->spd_eternal = flg; 6099 if (flg) { 6100 mat->structural_symmetry_eternal = PETSC_TRUE; 6101 mat->symmetry_eternal = PETSC_TRUE; 6102 } 6103 break; 6104 case MAT_STRUCTURE_ONLY: 6105 mat->structure_only = flg; 6106 break; 6107 case MAT_SORTED_FULL: 6108 mat->sortedfull = flg; 6109 break; 6110 default: 6111 break; 6112 } 6113 PetscTryTypeMethod(mat, setoption, op, flg); 6114 PetscFunctionReturn(PETSC_SUCCESS); 6115 } 6116 6117 /*@ 6118 MatGetOption - Gets a parameter option that has been set for a matrix. 6119 6120 Logically Collective 6121 6122 Input Parameters: 6123 + mat - the matrix 6124 - op - the option, this only responds to certain options, check the code for which ones 6125 6126 Output Parameter: 6127 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6128 6129 Level: intermediate 6130 6131 Notes: 6132 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6133 6134 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6135 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6136 6137 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6138 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6139 @*/ 6140 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6141 { 6142 PetscFunctionBegin; 6143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6144 PetscValidType(mat, 1); 6145 6146 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); 6147 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()"); 6148 6149 switch (op) { 6150 case MAT_NO_OFF_PROC_ENTRIES: 6151 *flg = mat->nooffprocentries; 6152 break; 6153 case MAT_NO_OFF_PROC_ZERO_ROWS: 6154 *flg = mat->nooffproczerorows; 6155 break; 6156 case MAT_SYMMETRIC: 6157 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6158 break; 6159 case MAT_HERMITIAN: 6160 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6161 break; 6162 case MAT_STRUCTURALLY_SYMMETRIC: 6163 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6164 break; 6165 case MAT_SPD: 6166 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6167 break; 6168 case MAT_SYMMETRY_ETERNAL: 6169 *flg = mat->symmetry_eternal; 6170 break; 6171 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6172 *flg = mat->symmetry_eternal; 6173 break; 6174 default: 6175 break; 6176 } 6177 PetscFunctionReturn(PETSC_SUCCESS); 6178 } 6179 6180 /*@ 6181 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6182 this routine retains the old nonzero structure. 6183 6184 Logically Collective 6185 6186 Input Parameter: 6187 . mat - the matrix 6188 6189 Level: intermediate 6190 6191 Note: 6192 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. 6193 See the Performance chapter of the users manual for information on preallocating matrices. 6194 6195 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6196 @*/ 6197 PetscErrorCode MatZeroEntries(Mat mat) 6198 { 6199 PetscFunctionBegin; 6200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6201 PetscValidType(mat, 1); 6202 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6203 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"); 6204 MatCheckPreallocated(mat, 1); 6205 6206 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6207 PetscUseTypeMethod(mat, zeroentries); 6208 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6209 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6210 PetscFunctionReturn(PETSC_SUCCESS); 6211 } 6212 6213 /*@ 6214 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6215 of a set of rows and columns of a matrix. 6216 6217 Collective 6218 6219 Input Parameters: 6220 + mat - the matrix 6221 . numRows - the number of rows/columns to zero 6222 . rows - the global row indices 6223 . diag - value put in the diagonal of the eliminated rows 6224 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6225 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6226 6227 Level: intermediate 6228 6229 Notes: 6230 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6231 6232 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6233 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 6234 6235 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6236 Krylov method to take advantage of the known solution on the zeroed rows. 6237 6238 For the parallel case, all processes that share the matrix (i.e., 6239 those in the communicator used for matrix creation) MUST call this 6240 routine, regardless of whether any rows being zeroed are owned by 6241 them. 6242 6243 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6244 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 6245 missing. 6246 6247 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6248 list only rows local to itself). 6249 6250 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6251 6252 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6253 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6254 @*/ 6255 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6256 { 6257 PetscFunctionBegin; 6258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6259 PetscValidType(mat, 1); 6260 if (numRows) PetscAssertPointer(rows, 3); 6261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6263 MatCheckPreallocated(mat, 1); 6264 6265 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6266 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6267 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6268 PetscFunctionReturn(PETSC_SUCCESS); 6269 } 6270 6271 /*@ 6272 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6273 of a set of rows and columns of a matrix. 6274 6275 Collective 6276 6277 Input Parameters: 6278 + mat - the matrix 6279 . is - the rows to zero 6280 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6281 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6282 - b - optional vector of right-hand side, that will be adjusted by provided solution 6283 6284 Level: intermediate 6285 6286 Note: 6287 See `MatZeroRowsColumns()` for details on how this routine operates. 6288 6289 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6290 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6291 @*/ 6292 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6293 { 6294 PetscInt numRows; 6295 const PetscInt *rows; 6296 6297 PetscFunctionBegin; 6298 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6299 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6300 PetscValidType(mat, 1); 6301 PetscValidType(is, 2); 6302 PetscCall(ISGetLocalSize(is, &numRows)); 6303 PetscCall(ISGetIndices(is, &rows)); 6304 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6305 PetscCall(ISRestoreIndices(is, &rows)); 6306 PetscFunctionReturn(PETSC_SUCCESS); 6307 } 6308 6309 /*@ 6310 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6311 of a set of rows of a matrix. 6312 6313 Collective 6314 6315 Input Parameters: 6316 + mat - the matrix 6317 . numRows - the number of rows to zero 6318 . rows - the global row indices 6319 . diag - value put in the diagonal of the zeroed rows 6320 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6321 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6322 6323 Level: intermediate 6324 6325 Notes: 6326 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6327 6328 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6329 6330 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6331 Krylov method to take advantage of the known solution on the zeroed rows. 6332 6333 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) 6334 from the matrix. 6335 6336 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6337 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6338 formats this does not alter the nonzero structure. 6339 6340 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6341 of the matrix is not changed the values are 6342 merely zeroed. 6343 6344 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6345 formats can optionally remove the main diagonal entry from the 6346 nonzero structure as well, by passing 0.0 as the final argument). 6347 6348 For the parallel case, all processes that share the matrix (i.e., 6349 those in the communicator used for matrix creation) MUST call this 6350 routine, regardless of whether any rows being zeroed are owned by 6351 them. 6352 6353 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6354 list only rows local to itself). 6355 6356 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6357 owns that are to be zeroed. This saves a global synchronization in the implementation. 6358 6359 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6360 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6361 @*/ 6362 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6363 { 6364 PetscFunctionBegin; 6365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6366 PetscValidType(mat, 1); 6367 if (numRows) PetscAssertPointer(rows, 3); 6368 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6369 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6370 MatCheckPreallocated(mat, 1); 6371 6372 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6373 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6374 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6375 PetscFunctionReturn(PETSC_SUCCESS); 6376 } 6377 6378 /*@ 6379 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6380 of a set of rows of a matrix indicated by an `IS` 6381 6382 Collective 6383 6384 Input Parameters: 6385 + mat - the matrix 6386 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6387 . diag - value put in all diagonals of eliminated rows 6388 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6389 - b - optional vector of right-hand side, that will be adjusted by provided solution 6390 6391 Level: intermediate 6392 6393 Note: 6394 See `MatZeroRows()` for details on how this routine operates. 6395 6396 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6397 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6398 @*/ 6399 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6400 { 6401 PetscInt numRows = 0; 6402 const PetscInt *rows = NULL; 6403 6404 PetscFunctionBegin; 6405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6406 PetscValidType(mat, 1); 6407 if (is) { 6408 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6409 PetscCall(ISGetLocalSize(is, &numRows)); 6410 PetscCall(ISGetIndices(is, &rows)); 6411 } 6412 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6413 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6414 PetscFunctionReturn(PETSC_SUCCESS); 6415 } 6416 6417 /*@ 6418 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6419 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6420 6421 Collective 6422 6423 Input Parameters: 6424 + mat - the matrix 6425 . numRows - the number of rows to remove 6426 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6427 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6428 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6429 - b - optional vector of right-hand side, that will be adjusted by provided solution 6430 6431 Level: intermediate 6432 6433 Notes: 6434 See `MatZeroRows()` for details on how this routine operates. 6435 6436 The grid coordinates are across the entire grid, not just the local portion 6437 6438 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6439 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6440 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6441 `DM_BOUNDARY_PERIODIC` boundary type. 6442 6443 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 6444 a single value per point) you can skip filling those indices. 6445 6446 Fortran Note: 6447 `idxm` and `idxn` should be declared as 6448 $ MatStencil idxm(4, m) 6449 and the values inserted using 6450 .vb 6451 idxm(MatStencil_i, 1) = i 6452 idxm(MatStencil_j, 1) = j 6453 idxm(MatStencil_k, 1) = k 6454 idxm(MatStencil_c, 1) = c 6455 etc 6456 .ve 6457 6458 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6459 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6460 @*/ 6461 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6462 { 6463 PetscInt dim = mat->stencil.dim; 6464 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6465 PetscInt *dims = mat->stencil.dims + 1; 6466 PetscInt *starts = mat->stencil.starts; 6467 PetscInt *dxm = (PetscInt *)rows; 6468 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6469 6470 PetscFunctionBegin; 6471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6472 PetscValidType(mat, 1); 6473 if (numRows) PetscAssertPointer(rows, 3); 6474 6475 PetscCall(PetscMalloc1(numRows, &jdxm)); 6476 for (i = 0; i < numRows; ++i) { 6477 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6478 for (j = 0; j < 3 - sdim; ++j) dxm++; 6479 /* Local index in X dir */ 6480 tmp = *dxm++ - starts[0]; 6481 /* Loop over remaining dimensions */ 6482 for (j = 0; j < dim - 1; ++j) { 6483 /* If nonlocal, set index to be negative */ 6484 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6485 /* Update local index */ 6486 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6487 } 6488 /* Skip component slot if necessary */ 6489 if (mat->stencil.noc) dxm++; 6490 /* Local row number */ 6491 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6492 } 6493 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6494 PetscCall(PetscFree(jdxm)); 6495 PetscFunctionReturn(PETSC_SUCCESS); 6496 } 6497 6498 /*@ 6499 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6500 of a set of rows and columns of a matrix. 6501 6502 Collective 6503 6504 Input Parameters: 6505 + mat - the matrix 6506 . numRows - the number of rows/columns to remove 6507 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6508 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6509 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6510 - b - optional vector of right-hand side, that will be adjusted by provided solution 6511 6512 Level: intermediate 6513 6514 Notes: 6515 See `MatZeroRowsColumns()` for details on how this routine operates. 6516 6517 The grid coordinates are across the entire grid, not just the local portion 6518 6519 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6520 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6521 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6522 `DM_BOUNDARY_PERIODIC` boundary type. 6523 6524 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 6525 a single value per point) you can skip filling those indices. 6526 6527 Fortran Note: 6528 `idxm` and `idxn` should be declared as 6529 $ MatStencil idxm(4, m) 6530 and the values inserted using 6531 .vb 6532 idxm(MatStencil_i, 1) = i 6533 idxm(MatStencil_j, 1) = j 6534 idxm(MatStencil_k, 1) = k 6535 idxm(MatStencil_c, 1) = c 6536 etc 6537 .ve 6538 6539 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6540 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6541 @*/ 6542 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6543 { 6544 PetscInt dim = mat->stencil.dim; 6545 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6546 PetscInt *dims = mat->stencil.dims + 1; 6547 PetscInt *starts = mat->stencil.starts; 6548 PetscInt *dxm = (PetscInt *)rows; 6549 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6550 6551 PetscFunctionBegin; 6552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6553 PetscValidType(mat, 1); 6554 if (numRows) PetscAssertPointer(rows, 3); 6555 6556 PetscCall(PetscMalloc1(numRows, &jdxm)); 6557 for (i = 0; i < numRows; ++i) { 6558 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6559 for (j = 0; j < 3 - sdim; ++j) dxm++; 6560 /* Local index in X dir */ 6561 tmp = *dxm++ - starts[0]; 6562 /* Loop over remaining dimensions */ 6563 for (j = 0; j < dim - 1; ++j) { 6564 /* If nonlocal, set index to be negative */ 6565 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6566 /* Update local index */ 6567 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6568 } 6569 /* Skip component slot if necessary */ 6570 if (mat->stencil.noc) dxm++; 6571 /* Local row number */ 6572 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6573 } 6574 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6575 PetscCall(PetscFree(jdxm)); 6576 PetscFunctionReturn(PETSC_SUCCESS); 6577 } 6578 6579 /*@ 6580 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6581 of a set of rows of a matrix; using local numbering of rows. 6582 6583 Collective 6584 6585 Input Parameters: 6586 + mat - the matrix 6587 . numRows - the number of rows to remove 6588 . rows - the local row indices 6589 . diag - value put in all diagonals of eliminated rows 6590 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6591 - b - optional vector of right-hand side, that will be adjusted by provided solution 6592 6593 Level: intermediate 6594 6595 Notes: 6596 Before calling `MatZeroRowsLocal()`, the user must first set the 6597 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6598 6599 See `MatZeroRows()` for details on how this routine operates. 6600 6601 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6602 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6603 @*/ 6604 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6605 { 6606 PetscFunctionBegin; 6607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6608 PetscValidType(mat, 1); 6609 if (numRows) PetscAssertPointer(rows, 3); 6610 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6611 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6612 MatCheckPreallocated(mat, 1); 6613 6614 if (mat->ops->zerorowslocal) { 6615 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6616 } else { 6617 IS is, newis; 6618 const PetscInt *newRows; 6619 6620 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6621 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6622 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6623 PetscCall(ISGetIndices(newis, &newRows)); 6624 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6625 PetscCall(ISRestoreIndices(newis, &newRows)); 6626 PetscCall(ISDestroy(&newis)); 6627 PetscCall(ISDestroy(&is)); 6628 } 6629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6630 PetscFunctionReturn(PETSC_SUCCESS); 6631 } 6632 6633 /*@ 6634 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6635 of a set of rows of a matrix; using local numbering of rows. 6636 6637 Collective 6638 6639 Input Parameters: 6640 + mat - the matrix 6641 . is - index set of rows to remove 6642 . diag - value put in all diagonals of eliminated rows 6643 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6644 - b - optional vector of right-hand side, that will be adjusted by provided solution 6645 6646 Level: intermediate 6647 6648 Notes: 6649 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6650 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6651 6652 See `MatZeroRows()` for details on how this routine operates. 6653 6654 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6655 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6656 @*/ 6657 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6658 { 6659 PetscInt numRows; 6660 const PetscInt *rows; 6661 6662 PetscFunctionBegin; 6663 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6664 PetscValidType(mat, 1); 6665 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6666 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6667 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6668 MatCheckPreallocated(mat, 1); 6669 6670 PetscCall(ISGetLocalSize(is, &numRows)); 6671 PetscCall(ISGetIndices(is, &rows)); 6672 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6673 PetscCall(ISRestoreIndices(is, &rows)); 6674 PetscFunctionReturn(PETSC_SUCCESS); 6675 } 6676 6677 /*@ 6678 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6679 of a set of rows and columns of a matrix; using local numbering of rows. 6680 6681 Collective 6682 6683 Input Parameters: 6684 + mat - the matrix 6685 . numRows - the number of rows to remove 6686 . rows - the global row indices 6687 . diag - value put in all diagonals of eliminated rows 6688 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6689 - b - optional vector of right-hand side, that will be adjusted by provided solution 6690 6691 Level: intermediate 6692 6693 Notes: 6694 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6695 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6696 6697 See `MatZeroRowsColumns()` for details on how this routine operates. 6698 6699 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6700 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6701 @*/ 6702 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6703 { 6704 IS is, newis; 6705 const PetscInt *newRows; 6706 6707 PetscFunctionBegin; 6708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6709 PetscValidType(mat, 1); 6710 if (numRows) PetscAssertPointer(rows, 3); 6711 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6712 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6713 MatCheckPreallocated(mat, 1); 6714 6715 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6716 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6717 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6718 PetscCall(ISGetIndices(newis, &newRows)); 6719 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6720 PetscCall(ISRestoreIndices(newis, &newRows)); 6721 PetscCall(ISDestroy(&newis)); 6722 PetscCall(ISDestroy(&is)); 6723 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6724 PetscFunctionReturn(PETSC_SUCCESS); 6725 } 6726 6727 /*@ 6728 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6729 of a set of rows and columns of a matrix; using local numbering of rows. 6730 6731 Collective 6732 6733 Input Parameters: 6734 + mat - the matrix 6735 . is - index set of rows to remove 6736 . diag - value put in all diagonals of eliminated rows 6737 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6738 - b - optional vector of right-hand side, that will be adjusted by provided solution 6739 6740 Level: intermediate 6741 6742 Notes: 6743 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6744 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6745 6746 See `MatZeroRowsColumns()` for details on how this routine operates. 6747 6748 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6749 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6750 @*/ 6751 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6752 { 6753 PetscInt numRows; 6754 const PetscInt *rows; 6755 6756 PetscFunctionBegin; 6757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6758 PetscValidType(mat, 1); 6759 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6760 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6761 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6762 MatCheckPreallocated(mat, 1); 6763 6764 PetscCall(ISGetLocalSize(is, &numRows)); 6765 PetscCall(ISGetIndices(is, &rows)); 6766 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6767 PetscCall(ISRestoreIndices(is, &rows)); 6768 PetscFunctionReturn(PETSC_SUCCESS); 6769 } 6770 6771 /*@ 6772 MatGetSize - Returns the numbers of rows and columns in a matrix. 6773 6774 Not Collective 6775 6776 Input Parameter: 6777 . mat - the matrix 6778 6779 Output Parameters: 6780 + m - the number of global rows 6781 - n - the number of global columns 6782 6783 Level: beginner 6784 6785 Note: 6786 Both output parameters can be `NULL` on input. 6787 6788 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6789 @*/ 6790 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6791 { 6792 PetscFunctionBegin; 6793 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6794 if (m) *m = mat->rmap->N; 6795 if (n) *n = mat->cmap->N; 6796 PetscFunctionReturn(PETSC_SUCCESS); 6797 } 6798 6799 /*@ 6800 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6801 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6802 6803 Not Collective 6804 6805 Input Parameter: 6806 . mat - the matrix 6807 6808 Output Parameters: 6809 + m - the number of local rows, use `NULL` to not obtain this value 6810 - n - the number of local columns, use `NULL` to not obtain this value 6811 6812 Level: beginner 6813 6814 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6815 @*/ 6816 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6817 { 6818 PetscFunctionBegin; 6819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6820 if (m) PetscAssertPointer(m, 2); 6821 if (n) PetscAssertPointer(n, 3); 6822 if (m) *m = mat->rmap->n; 6823 if (n) *n = mat->cmap->n; 6824 PetscFunctionReturn(PETSC_SUCCESS); 6825 } 6826 6827 /*@ 6828 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6829 vector one multiplies this matrix by that are owned by this processor. 6830 6831 Not Collective, unless matrix has not been allocated, then collective 6832 6833 Input Parameter: 6834 . mat - the matrix 6835 6836 Output Parameters: 6837 + m - the global index of the first local column, use `NULL` to not obtain this value 6838 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6839 6840 Level: developer 6841 6842 Notes: 6843 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6844 6845 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6846 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6847 6848 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6849 the local values in the matrix. 6850 6851 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6852 Layouts](sec_matlayout) for details on matrix layouts. 6853 6854 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6855 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6856 @*/ 6857 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6858 { 6859 PetscFunctionBegin; 6860 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6861 PetscValidType(mat, 1); 6862 if (m) PetscAssertPointer(m, 2); 6863 if (n) PetscAssertPointer(n, 3); 6864 MatCheckPreallocated(mat, 1); 6865 if (m) *m = mat->cmap->rstart; 6866 if (n) *n = mat->cmap->rend; 6867 PetscFunctionReturn(PETSC_SUCCESS); 6868 } 6869 6870 /*@ 6871 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6872 this MPI process. 6873 6874 Not Collective 6875 6876 Input Parameter: 6877 . mat - the matrix 6878 6879 Output Parameters: 6880 + m - the global index of the first local row, use `NULL` to not obtain this value 6881 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6882 6883 Level: beginner 6884 6885 Notes: 6886 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6887 6888 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6889 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6890 6891 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6892 the local values in the matrix. 6893 6894 The high argument is one more than the last element stored locally. 6895 6896 For all matrices it returns the range of matrix rows associated with rows of a vector that 6897 would contain the result of a matrix vector product with this matrix. See [Matrix 6898 Layouts](sec_matlayout) for details on matrix layouts. 6899 6900 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6901 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6902 @*/ 6903 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6904 { 6905 PetscFunctionBegin; 6906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6907 PetscValidType(mat, 1); 6908 if (m) PetscAssertPointer(m, 2); 6909 if (n) PetscAssertPointer(n, 3); 6910 MatCheckPreallocated(mat, 1); 6911 if (m) *m = mat->rmap->rstart; 6912 if (n) *n = mat->rmap->rend; 6913 PetscFunctionReturn(PETSC_SUCCESS); 6914 } 6915 6916 /*@C 6917 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6918 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6919 6920 Not Collective, unless matrix has not been allocated 6921 6922 Input Parameter: 6923 . mat - the matrix 6924 6925 Output Parameter: 6926 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6927 where `size` is the number of MPI processes used by `mat` 6928 6929 Level: beginner 6930 6931 Notes: 6932 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6933 6934 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6935 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6936 6937 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6938 the local values in the matrix. 6939 6940 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6941 would contain the result of a matrix vector product with this matrix. See [Matrix 6942 Layouts](sec_matlayout) for details on matrix layouts. 6943 6944 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6945 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6946 `DMDAGetGhostCorners()`, `DM` 6947 @*/ 6948 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6949 { 6950 PetscFunctionBegin; 6951 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6952 PetscValidType(mat, 1); 6953 MatCheckPreallocated(mat, 1); 6954 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6955 PetscFunctionReturn(PETSC_SUCCESS); 6956 } 6957 6958 /*@C 6959 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6960 vector one multiplies this vector by that are owned by each processor. 6961 6962 Not Collective, unless matrix has not been allocated 6963 6964 Input Parameter: 6965 . mat - the matrix 6966 6967 Output Parameter: 6968 . ranges - start of each processors portion plus one more than the total length at the end 6969 6970 Level: beginner 6971 6972 Notes: 6973 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6974 6975 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6976 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6977 6978 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6979 the local values in the matrix. 6980 6981 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6982 Layouts](sec_matlayout) for details on matrix layouts. 6983 6984 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6985 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6986 `DMDAGetGhostCorners()`, `DM` 6987 @*/ 6988 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6989 { 6990 PetscFunctionBegin; 6991 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6992 PetscValidType(mat, 1); 6993 MatCheckPreallocated(mat, 1); 6994 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6995 PetscFunctionReturn(PETSC_SUCCESS); 6996 } 6997 6998 /*@ 6999 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7000 7001 Not Collective 7002 7003 Input Parameter: 7004 . A - matrix 7005 7006 Output Parameters: 7007 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7008 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7009 7010 Level: intermediate 7011 7012 Note: 7013 You should call `ISDestroy()` on the returned `IS` 7014 7015 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7016 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7017 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7018 details on matrix layouts. 7019 7020 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7021 @*/ 7022 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7023 { 7024 PetscErrorCode (*f)(Mat, IS *, IS *); 7025 7026 PetscFunctionBegin; 7027 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7028 PetscValidType(A, 1); 7029 MatCheckPreallocated(A, 1); 7030 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7031 if (f) { 7032 PetscCall((*f)(A, rows, cols)); 7033 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7034 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7035 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7036 } 7037 PetscFunctionReturn(PETSC_SUCCESS); 7038 } 7039 7040 /*@ 7041 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7042 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7043 to complete the factorization. 7044 7045 Collective 7046 7047 Input Parameters: 7048 + fact - the factorized matrix obtained with `MatGetFactor()` 7049 . mat - the matrix 7050 . row - row permutation 7051 . col - column permutation 7052 - info - structure containing 7053 .vb 7054 levels - number of levels of fill. 7055 expected fill - as ratio of original fill. 7056 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7057 missing diagonal entries) 7058 .ve 7059 7060 Level: developer 7061 7062 Notes: 7063 See [Matrix Factorization](sec_matfactor) for additional information. 7064 7065 Most users should employ the `KSP` interface for linear solvers 7066 instead of working directly with matrix algebra routines such as this. 7067 See, e.g., `KSPCreate()`. 7068 7069 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7070 7071 Developer Note: 7072 The Fortran interface is not autogenerated as the 7073 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7074 7075 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7076 `MatGetOrdering()`, `MatFactorInfo` 7077 @*/ 7078 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7079 { 7080 PetscFunctionBegin; 7081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7082 PetscValidType(mat, 2); 7083 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7084 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7085 PetscAssertPointer(info, 5); 7086 PetscAssertPointer(fact, 1); 7087 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7088 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7089 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7090 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7091 MatCheckPreallocated(mat, 2); 7092 7093 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7094 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7095 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7096 PetscFunctionReturn(PETSC_SUCCESS); 7097 } 7098 7099 /*@ 7100 MatICCFactorSymbolic - Performs symbolic incomplete 7101 Cholesky factorization for a symmetric matrix. Use 7102 `MatCholeskyFactorNumeric()` to complete the factorization. 7103 7104 Collective 7105 7106 Input Parameters: 7107 + fact - the factorized matrix obtained with `MatGetFactor()` 7108 . mat - the matrix to be factored 7109 . perm - row and column permutation 7110 - info - structure containing 7111 .vb 7112 levels - number of levels of fill. 7113 expected fill - as ratio of original fill. 7114 .ve 7115 7116 Level: developer 7117 7118 Notes: 7119 Most users should employ the `KSP` interface for linear solvers 7120 instead of working directly with matrix algebra routines such as this. 7121 See, e.g., `KSPCreate()`. 7122 7123 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7124 7125 Developer Note: 7126 The Fortran interface is not autogenerated as the 7127 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7128 7129 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7130 @*/ 7131 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7132 { 7133 PetscFunctionBegin; 7134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7135 PetscValidType(mat, 2); 7136 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7137 PetscAssertPointer(info, 4); 7138 PetscAssertPointer(fact, 1); 7139 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7140 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7141 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7143 MatCheckPreallocated(mat, 2); 7144 7145 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7146 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7147 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7148 PetscFunctionReturn(PETSC_SUCCESS); 7149 } 7150 7151 /*@C 7152 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7153 points to an array of valid matrices, they may be reused to store the new 7154 submatrices. 7155 7156 Collective 7157 7158 Input Parameters: 7159 + mat - the matrix 7160 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7161 . irow - index set of rows to extract 7162 . icol - index set of columns to extract 7163 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7164 7165 Output Parameter: 7166 . submat - the array of submatrices 7167 7168 Level: advanced 7169 7170 Notes: 7171 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7172 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7173 to extract a parallel submatrix. 7174 7175 Some matrix types place restrictions on the row and column 7176 indices, such as that they be sorted or that they be equal to each other. 7177 7178 The index sets may not have duplicate entries. 7179 7180 When extracting submatrices from a parallel matrix, each processor can 7181 form a different submatrix by setting the rows and columns of its 7182 individual index sets according to the local submatrix desired. 7183 7184 When finished using the submatrices, the user should destroy 7185 them with `MatDestroySubMatrices()`. 7186 7187 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7188 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7189 7190 This routine creates the matrices in submat; you should NOT create them before 7191 calling it. It also allocates the array of matrix pointers submat. 7192 7193 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7194 request one row/column in a block, they must request all rows/columns that are in 7195 that block. For example, if the block size is 2 you cannot request just row 0 and 7196 column 0. 7197 7198 Fortran Note: 7199 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7200 7201 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7202 @*/ 7203 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7204 { 7205 PetscInt i; 7206 PetscBool eq; 7207 7208 PetscFunctionBegin; 7209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7210 PetscValidType(mat, 1); 7211 if (n) { 7212 PetscAssertPointer(irow, 3); 7213 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7214 PetscAssertPointer(icol, 4); 7215 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7216 } 7217 PetscAssertPointer(submat, 6); 7218 if (n && scall == MAT_REUSE_MATRIX) { 7219 PetscAssertPointer(*submat, 6); 7220 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7221 } 7222 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7223 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7224 MatCheckPreallocated(mat, 1); 7225 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7226 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7227 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7228 for (i = 0; i < n; i++) { 7229 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7230 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7231 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7232 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7233 if (mat->boundtocpu && mat->bindingpropagates) { 7234 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7235 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7236 } 7237 #endif 7238 } 7239 PetscFunctionReturn(PETSC_SUCCESS); 7240 } 7241 7242 /*@C 7243 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7244 7245 Collective 7246 7247 Input Parameters: 7248 + mat - the matrix 7249 . n - the number of submatrixes to be extracted 7250 . irow - index set of rows to extract 7251 . icol - index set of columns to extract 7252 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7253 7254 Output Parameter: 7255 . submat - the array of submatrices 7256 7257 Level: advanced 7258 7259 Note: 7260 This is used by `PCGASM` 7261 7262 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7263 @*/ 7264 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7265 { 7266 PetscInt i; 7267 PetscBool eq; 7268 7269 PetscFunctionBegin; 7270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7271 PetscValidType(mat, 1); 7272 if (n) { 7273 PetscAssertPointer(irow, 3); 7274 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7275 PetscAssertPointer(icol, 4); 7276 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7277 } 7278 PetscAssertPointer(submat, 6); 7279 if (n && scall == MAT_REUSE_MATRIX) { 7280 PetscAssertPointer(*submat, 6); 7281 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7282 } 7283 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7284 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7285 MatCheckPreallocated(mat, 1); 7286 7287 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7288 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7289 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7290 for (i = 0; i < n; i++) { 7291 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7292 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7293 } 7294 PetscFunctionReturn(PETSC_SUCCESS); 7295 } 7296 7297 /*@C 7298 MatDestroyMatrices - Destroys an array of matrices. 7299 7300 Collective 7301 7302 Input Parameters: 7303 + n - the number of local matrices 7304 - mat - the matrices (this is a pointer to the array of matrices) 7305 7306 Level: advanced 7307 7308 Notes: 7309 Frees not only the matrices, but also the array that contains the matrices 7310 7311 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7312 7313 Fortran Note: 7314 Does not free the `mat` array. 7315 7316 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7317 @*/ 7318 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7319 { 7320 PetscInt i; 7321 7322 PetscFunctionBegin; 7323 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7324 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7325 PetscAssertPointer(mat, 2); 7326 7327 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7328 7329 /* memory is allocated even if n = 0 */ 7330 PetscCall(PetscFree(*mat)); 7331 PetscFunctionReturn(PETSC_SUCCESS); 7332 } 7333 7334 /*@C 7335 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7336 7337 Collective 7338 7339 Input Parameters: 7340 + n - the number of local matrices 7341 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7342 sequence of `MatCreateSubMatrices()`) 7343 7344 Level: advanced 7345 7346 Note: 7347 Frees not only the matrices, but also the array that contains the matrices 7348 7349 Fortran Note: 7350 Does not free the `mat` array. 7351 7352 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7353 @*/ 7354 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7355 { 7356 Mat mat0; 7357 7358 PetscFunctionBegin; 7359 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7360 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7361 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7362 PetscAssertPointer(mat, 2); 7363 7364 mat0 = (*mat)[0]; 7365 if (mat0 && mat0->ops->destroysubmatrices) { 7366 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7367 } else { 7368 PetscCall(MatDestroyMatrices(n, mat)); 7369 } 7370 PetscFunctionReturn(PETSC_SUCCESS); 7371 } 7372 7373 /*@ 7374 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7375 7376 Collective 7377 7378 Input Parameter: 7379 . mat - the matrix 7380 7381 Output Parameter: 7382 . matstruct - the sequential matrix with the nonzero structure of `mat` 7383 7384 Level: developer 7385 7386 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7387 @*/ 7388 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7389 { 7390 PetscFunctionBegin; 7391 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7392 PetscAssertPointer(matstruct, 2); 7393 7394 PetscValidType(mat, 1); 7395 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7396 MatCheckPreallocated(mat, 1); 7397 7398 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7399 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7400 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7401 PetscFunctionReturn(PETSC_SUCCESS); 7402 } 7403 7404 /*@C 7405 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7406 7407 Collective 7408 7409 Input Parameter: 7410 . mat - the matrix 7411 7412 Level: advanced 7413 7414 Note: 7415 This is not needed, one can just call `MatDestroy()` 7416 7417 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7418 @*/ 7419 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7420 { 7421 PetscFunctionBegin; 7422 PetscAssertPointer(mat, 1); 7423 PetscCall(MatDestroy(mat)); 7424 PetscFunctionReturn(PETSC_SUCCESS); 7425 } 7426 7427 /*@ 7428 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7429 replaces the index sets by larger ones that represent submatrices with 7430 additional overlap. 7431 7432 Collective 7433 7434 Input Parameters: 7435 + mat - the matrix 7436 . n - the number of index sets 7437 . is - the array of index sets (these index sets will changed during the call) 7438 - ov - the additional overlap requested 7439 7440 Options Database Key: 7441 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7442 7443 Level: developer 7444 7445 Note: 7446 The computed overlap preserves the matrix block sizes when the blocks are square. 7447 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7448 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7449 7450 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7451 @*/ 7452 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7453 { 7454 PetscInt i, bs, cbs; 7455 7456 PetscFunctionBegin; 7457 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7458 PetscValidType(mat, 1); 7459 PetscValidLogicalCollectiveInt(mat, n, 2); 7460 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7461 if (n) { 7462 PetscAssertPointer(is, 3); 7463 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7464 } 7465 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7466 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7467 MatCheckPreallocated(mat, 1); 7468 7469 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7470 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7471 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7472 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7473 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7474 if (bs == cbs) { 7475 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7476 } 7477 PetscFunctionReturn(PETSC_SUCCESS); 7478 } 7479 7480 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7481 7482 /*@ 7483 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7484 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7485 additional overlap. 7486 7487 Collective 7488 7489 Input Parameters: 7490 + mat - the matrix 7491 . n - the number of index sets 7492 . is - the array of index sets (these index sets will changed during the call) 7493 - ov - the additional overlap requested 7494 7495 ` Options Database Key: 7496 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7497 7498 Level: developer 7499 7500 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7501 @*/ 7502 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7503 { 7504 PetscInt i; 7505 7506 PetscFunctionBegin; 7507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7508 PetscValidType(mat, 1); 7509 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7510 if (n) { 7511 PetscAssertPointer(is, 3); 7512 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7513 } 7514 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7515 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7516 MatCheckPreallocated(mat, 1); 7517 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7518 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7519 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7520 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7521 PetscFunctionReturn(PETSC_SUCCESS); 7522 } 7523 7524 /*@ 7525 MatGetBlockSize - Returns the matrix block size. 7526 7527 Not Collective 7528 7529 Input Parameter: 7530 . mat - the matrix 7531 7532 Output Parameter: 7533 . bs - block size 7534 7535 Level: intermediate 7536 7537 Notes: 7538 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7539 7540 If the block size has not been set yet this routine returns 1. 7541 7542 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7543 @*/ 7544 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7545 { 7546 PetscFunctionBegin; 7547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7548 PetscAssertPointer(bs, 2); 7549 *bs = PetscAbs(mat->rmap->bs); 7550 PetscFunctionReturn(PETSC_SUCCESS); 7551 } 7552 7553 /*@ 7554 MatGetBlockSizes - Returns the matrix block row and column sizes. 7555 7556 Not Collective 7557 7558 Input Parameter: 7559 . mat - the matrix 7560 7561 Output Parameters: 7562 + rbs - row block size 7563 - cbs - column block size 7564 7565 Level: intermediate 7566 7567 Notes: 7568 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7569 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7570 7571 If a block size has not been set yet this routine returns 1. 7572 7573 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7574 @*/ 7575 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7576 { 7577 PetscFunctionBegin; 7578 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7579 if (rbs) PetscAssertPointer(rbs, 2); 7580 if (cbs) PetscAssertPointer(cbs, 3); 7581 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7582 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7583 PetscFunctionReturn(PETSC_SUCCESS); 7584 } 7585 7586 /*@ 7587 MatSetBlockSize - Sets the matrix block size. 7588 7589 Logically Collective 7590 7591 Input Parameters: 7592 + mat - the matrix 7593 - bs - block size 7594 7595 Level: intermediate 7596 7597 Notes: 7598 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7599 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7600 7601 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7602 is compatible with the matrix local sizes. 7603 7604 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7605 @*/ 7606 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7607 { 7608 PetscFunctionBegin; 7609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7610 PetscValidLogicalCollectiveInt(mat, bs, 2); 7611 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7612 PetscFunctionReturn(PETSC_SUCCESS); 7613 } 7614 7615 typedef struct { 7616 PetscInt n; 7617 IS *is; 7618 Mat *mat; 7619 PetscObjectState nonzerostate; 7620 Mat C; 7621 } EnvelopeData; 7622 7623 static PetscErrorCode EnvelopeDataDestroy(void *ptr) 7624 { 7625 EnvelopeData *edata = (EnvelopeData *)ptr; 7626 7627 PetscFunctionBegin; 7628 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7629 PetscCall(PetscFree(edata->is)); 7630 PetscCall(PetscFree(edata)); 7631 PetscFunctionReturn(PETSC_SUCCESS); 7632 } 7633 7634 /*@ 7635 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7636 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7637 7638 Collective 7639 7640 Input Parameter: 7641 . mat - the matrix 7642 7643 Level: intermediate 7644 7645 Notes: 7646 There can be zeros within the blocks 7647 7648 The blocks can overlap between processes, including laying on more than two processes 7649 7650 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7651 @*/ 7652 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7653 { 7654 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7655 PetscInt *diag, *odiag, sc; 7656 VecScatter scatter; 7657 PetscScalar *seqv; 7658 const PetscScalar *parv; 7659 const PetscInt *ia, *ja; 7660 PetscBool set, flag, done; 7661 Mat AA = mat, A; 7662 MPI_Comm comm; 7663 PetscMPIInt rank, size, tag; 7664 MPI_Status status; 7665 PetscContainer container; 7666 EnvelopeData *edata; 7667 Vec seq, par; 7668 IS isglobal; 7669 7670 PetscFunctionBegin; 7671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7672 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7673 if (!set || !flag) { 7674 /* TODO: only needs nonzero structure of transpose */ 7675 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7676 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7677 } 7678 PetscCall(MatAIJGetLocalMat(AA, &A)); 7679 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7680 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7681 7682 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7683 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7684 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7685 PetscCallMPI(MPI_Comm_size(comm, &size)); 7686 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7687 7688 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7689 7690 if (rank > 0) { 7691 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7692 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7693 } 7694 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7695 for (i = 0; i < n; i++) { 7696 env = PetscMax(env, ja[ia[i + 1] - 1]); 7697 II = rstart + i; 7698 if (env == II) { 7699 starts[lblocks] = tbs; 7700 sizes[lblocks++] = 1 + II - tbs; 7701 tbs = 1 + II; 7702 } 7703 } 7704 if (rank < size - 1) { 7705 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7706 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7707 } 7708 7709 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7710 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7711 PetscCall(MatDestroy(&A)); 7712 7713 PetscCall(PetscNew(&edata)); 7714 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7715 edata->n = lblocks; 7716 /* create IS needed for extracting blocks from the original matrix */ 7717 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7718 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7719 7720 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7721 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7722 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7723 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7724 PetscCall(MatSetType(edata->C, MATAIJ)); 7725 7726 /* Communicate the start and end of each row, from each block to the correct rank */ 7727 /* TODO: Use PetscSF instead of VecScatter */ 7728 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7729 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7730 PetscCall(VecGetArrayWrite(seq, &seqv)); 7731 for (PetscInt i = 0; i < lblocks; i++) { 7732 for (PetscInt j = 0; j < sizes[i]; j++) { 7733 seqv[cnt] = starts[i]; 7734 seqv[cnt + 1] = starts[i] + sizes[i]; 7735 cnt += 2; 7736 } 7737 } 7738 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7739 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7740 sc -= cnt; 7741 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7742 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7743 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7744 PetscCall(ISDestroy(&isglobal)); 7745 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7746 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7747 PetscCall(VecScatterDestroy(&scatter)); 7748 PetscCall(VecDestroy(&seq)); 7749 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7750 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7751 PetscCall(VecGetArrayRead(par, &parv)); 7752 cnt = 0; 7753 PetscCall(MatGetSize(mat, NULL, &n)); 7754 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7755 PetscInt start, end, d = 0, od = 0; 7756 7757 start = (PetscInt)PetscRealPart(parv[cnt]); 7758 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7759 cnt += 2; 7760 7761 if (start < cstart) { 7762 od += cstart - start + n - cend; 7763 d += cend - cstart; 7764 } else if (start < cend) { 7765 od += n - cend; 7766 d += cend - start; 7767 } else od += n - start; 7768 if (end <= cstart) { 7769 od -= cstart - end + n - cend; 7770 d -= cend - cstart; 7771 } else if (end < cend) { 7772 od -= n - cend; 7773 d -= cend - end; 7774 } else od -= n - end; 7775 7776 odiag[i] = od; 7777 diag[i] = d; 7778 } 7779 PetscCall(VecRestoreArrayRead(par, &parv)); 7780 PetscCall(VecDestroy(&par)); 7781 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7782 PetscCall(PetscFree2(diag, odiag)); 7783 PetscCall(PetscFree2(sizes, starts)); 7784 7785 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7786 PetscCall(PetscContainerSetPointer(container, edata)); 7787 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode (*)(void *))EnvelopeDataDestroy)); 7788 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7789 PetscCall(PetscObjectDereference((PetscObject)container)); 7790 PetscFunctionReturn(PETSC_SUCCESS); 7791 } 7792 7793 /*@ 7794 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7795 7796 Collective 7797 7798 Input Parameters: 7799 + A - the matrix 7800 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7801 7802 Output Parameter: 7803 . C - matrix with inverted block diagonal of `A` 7804 7805 Level: advanced 7806 7807 Note: 7808 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7809 7810 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7811 @*/ 7812 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7813 { 7814 PetscContainer container; 7815 EnvelopeData *edata; 7816 PetscObjectState nonzerostate; 7817 7818 PetscFunctionBegin; 7819 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7820 if (!container) { 7821 PetscCall(MatComputeVariableBlockEnvelope(A)); 7822 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7823 } 7824 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7825 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7826 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7827 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7828 7829 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7830 *C = edata->C; 7831 7832 for (PetscInt i = 0; i < edata->n; i++) { 7833 Mat D; 7834 PetscScalar *dvalues; 7835 7836 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7837 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7838 PetscCall(MatSeqDenseInvert(D)); 7839 PetscCall(MatDenseGetArray(D, &dvalues)); 7840 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7841 PetscCall(MatDestroy(&D)); 7842 } 7843 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7844 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7845 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7846 PetscFunctionReturn(PETSC_SUCCESS); 7847 } 7848 7849 /*@ 7850 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7851 7852 Not Collective 7853 7854 Input Parameters: 7855 + mat - the matrix 7856 . nblocks - the number of blocks on this process, each block can only exist on a single process 7857 - bsizes - the block sizes 7858 7859 Level: intermediate 7860 7861 Notes: 7862 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7863 7864 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. 7865 7866 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7867 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7868 @*/ 7869 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7870 { 7871 PetscInt ncnt = 0, nlocal; 7872 7873 PetscFunctionBegin; 7874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7875 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7876 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); 7877 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7878 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); 7879 PetscCall(PetscFree(mat->bsizes)); 7880 mat->nblocks = nblocks; 7881 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7882 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7883 PetscFunctionReturn(PETSC_SUCCESS); 7884 } 7885 7886 /*@C 7887 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7888 7889 Not Collective; No Fortran Support 7890 7891 Input Parameter: 7892 . mat - the matrix 7893 7894 Output Parameters: 7895 + nblocks - the number of blocks on this process 7896 - bsizes - the block sizes 7897 7898 Level: intermediate 7899 7900 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7901 @*/ 7902 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7903 { 7904 PetscFunctionBegin; 7905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7906 if (nblocks) *nblocks = mat->nblocks; 7907 if (bsizes) *bsizes = mat->bsizes; 7908 PetscFunctionReturn(PETSC_SUCCESS); 7909 } 7910 7911 /*@ 7912 MatSetBlockSizes - Sets the matrix block row and column sizes. 7913 7914 Logically Collective 7915 7916 Input Parameters: 7917 + mat - the matrix 7918 . rbs - row block size 7919 - cbs - column block size 7920 7921 Level: intermediate 7922 7923 Notes: 7924 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7925 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7926 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7927 7928 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7929 are compatible with the matrix local sizes. 7930 7931 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7932 7933 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7934 @*/ 7935 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7936 { 7937 PetscFunctionBegin; 7938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7939 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7940 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7941 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7942 if (mat->rmap->refcnt) { 7943 ISLocalToGlobalMapping l2g = NULL; 7944 PetscLayout nmap = NULL; 7945 7946 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7947 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7948 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7949 mat->rmap = nmap; 7950 mat->rmap->mapping = l2g; 7951 } 7952 if (mat->cmap->refcnt) { 7953 ISLocalToGlobalMapping l2g = NULL; 7954 PetscLayout nmap = NULL; 7955 7956 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7957 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7958 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7959 mat->cmap = nmap; 7960 mat->cmap->mapping = l2g; 7961 } 7962 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7963 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7964 PetscFunctionReturn(PETSC_SUCCESS); 7965 } 7966 7967 /*@ 7968 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7969 7970 Logically Collective 7971 7972 Input Parameters: 7973 + mat - the matrix 7974 . fromRow - matrix from which to copy row block size 7975 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7976 7977 Level: developer 7978 7979 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7980 @*/ 7981 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7982 { 7983 PetscFunctionBegin; 7984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7985 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7986 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7987 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7988 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7989 PetscFunctionReturn(PETSC_SUCCESS); 7990 } 7991 7992 /*@ 7993 MatResidual - Default routine to calculate the residual r = b - Ax 7994 7995 Collective 7996 7997 Input Parameters: 7998 + mat - the matrix 7999 . b - the right-hand-side 8000 - x - the approximate solution 8001 8002 Output Parameter: 8003 . r - location to store the residual 8004 8005 Level: developer 8006 8007 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8008 @*/ 8009 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8010 { 8011 PetscFunctionBegin; 8012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8013 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8014 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8015 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8016 PetscValidType(mat, 1); 8017 MatCheckPreallocated(mat, 1); 8018 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8019 if (!mat->ops->residual) { 8020 PetscCall(MatMult(mat, x, r)); 8021 PetscCall(VecAYPX(r, -1.0, b)); 8022 } else { 8023 PetscUseTypeMethod(mat, residual, b, x, r); 8024 } 8025 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8026 PetscFunctionReturn(PETSC_SUCCESS); 8027 } 8028 8029 /*MC 8030 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8031 8032 Synopsis: 8033 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8034 8035 Not Collective 8036 8037 Input Parameters: 8038 + A - the matrix 8039 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8040 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8041 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8042 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8043 always used. 8044 8045 Output Parameters: 8046 + n - number of local rows in the (possibly compressed) matrix 8047 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8048 . ja - the column indices 8049 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8050 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8051 8052 Level: developer 8053 8054 Note: 8055 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8056 8057 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8058 M*/ 8059 8060 /*MC 8061 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8062 8063 Synopsis: 8064 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8065 8066 Not Collective 8067 8068 Input Parameters: 8069 + A - the matrix 8070 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8071 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8072 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8073 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8074 always used. 8075 . n - number of local rows in the (possibly compressed) matrix 8076 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8077 . ja - the column indices 8078 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8079 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8080 8081 Level: developer 8082 8083 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8084 M*/ 8085 8086 /*@C 8087 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8088 8089 Collective 8090 8091 Input Parameters: 8092 + mat - the matrix 8093 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8094 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8095 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8096 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8097 always used. 8098 8099 Output Parameters: 8100 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8101 . 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 8102 . ja - the column indices, use `NULL` if not needed 8103 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8104 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8105 8106 Level: developer 8107 8108 Notes: 8109 You CANNOT change any of the ia[] or ja[] values. 8110 8111 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8112 8113 Fortran Notes: 8114 Use 8115 .vb 8116 PetscInt, pointer :: ia(:),ja(:) 8117 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8118 ! Access the ith and jth entries via ia(i) and ja(j) 8119 .ve 8120 8121 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8122 8123 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8124 @*/ 8125 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8126 { 8127 PetscFunctionBegin; 8128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8129 PetscValidType(mat, 1); 8130 if (n) PetscAssertPointer(n, 5); 8131 if (ia) PetscAssertPointer(ia, 6); 8132 if (ja) PetscAssertPointer(ja, 7); 8133 if (done) PetscAssertPointer(done, 8); 8134 MatCheckPreallocated(mat, 1); 8135 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8136 else { 8137 if (done) *done = PETSC_TRUE; 8138 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8139 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8140 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8141 } 8142 PetscFunctionReturn(PETSC_SUCCESS); 8143 } 8144 8145 /*@C 8146 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8147 8148 Collective 8149 8150 Input Parameters: 8151 + mat - the matrix 8152 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8153 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8154 symmetrized 8155 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8156 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8157 always used. 8158 . n - number of columns in the (possibly compressed) matrix 8159 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8160 - ja - the row indices 8161 8162 Output Parameter: 8163 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8164 8165 Level: developer 8166 8167 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8168 @*/ 8169 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8170 { 8171 PetscFunctionBegin; 8172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8173 PetscValidType(mat, 1); 8174 PetscAssertPointer(n, 5); 8175 if (ia) PetscAssertPointer(ia, 6); 8176 if (ja) PetscAssertPointer(ja, 7); 8177 PetscAssertPointer(done, 8); 8178 MatCheckPreallocated(mat, 1); 8179 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8180 else { 8181 *done = PETSC_TRUE; 8182 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8183 } 8184 PetscFunctionReturn(PETSC_SUCCESS); 8185 } 8186 8187 /*@C 8188 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8189 8190 Collective 8191 8192 Input Parameters: 8193 + mat - the matrix 8194 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8195 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8196 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8197 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8198 always used. 8199 . n - size of (possibly compressed) matrix 8200 . ia - the row pointers 8201 - ja - the column indices 8202 8203 Output Parameter: 8204 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8205 8206 Level: developer 8207 8208 Note: 8209 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8210 us of the array after it has been restored. If you pass `NULL`, it will 8211 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8212 8213 Fortran Note: 8214 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8215 8216 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8217 @*/ 8218 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8219 { 8220 PetscFunctionBegin; 8221 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8222 PetscValidType(mat, 1); 8223 if (ia) PetscAssertPointer(ia, 6); 8224 if (ja) PetscAssertPointer(ja, 7); 8225 if (done) PetscAssertPointer(done, 8); 8226 MatCheckPreallocated(mat, 1); 8227 8228 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8229 else { 8230 if (done) *done = PETSC_TRUE; 8231 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8232 if (n) *n = 0; 8233 if (ia) *ia = NULL; 8234 if (ja) *ja = NULL; 8235 } 8236 PetscFunctionReturn(PETSC_SUCCESS); 8237 } 8238 8239 /*@C 8240 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8241 8242 Collective 8243 8244 Input Parameters: 8245 + mat - the matrix 8246 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8247 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8248 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8249 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8250 always used. 8251 8252 Output Parameters: 8253 + n - size of (possibly compressed) matrix 8254 . ia - the column pointers 8255 . ja - the row indices 8256 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8257 8258 Level: developer 8259 8260 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8261 @*/ 8262 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8263 { 8264 PetscFunctionBegin; 8265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8266 PetscValidType(mat, 1); 8267 if (ia) PetscAssertPointer(ia, 6); 8268 if (ja) PetscAssertPointer(ja, 7); 8269 PetscAssertPointer(done, 8); 8270 MatCheckPreallocated(mat, 1); 8271 8272 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8273 else { 8274 *done = PETSC_TRUE; 8275 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8276 if (n) *n = 0; 8277 if (ia) *ia = NULL; 8278 if (ja) *ja = NULL; 8279 } 8280 PetscFunctionReturn(PETSC_SUCCESS); 8281 } 8282 8283 /*@ 8284 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8285 `MatGetColumnIJ()`. 8286 8287 Collective 8288 8289 Input Parameters: 8290 + mat - the matrix 8291 . ncolors - maximum color value 8292 . n - number of entries in colorarray 8293 - colorarray - array indicating color for each column 8294 8295 Output Parameter: 8296 . iscoloring - coloring generated using colorarray information 8297 8298 Level: developer 8299 8300 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8301 @*/ 8302 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8303 { 8304 PetscFunctionBegin; 8305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8306 PetscValidType(mat, 1); 8307 PetscAssertPointer(colorarray, 4); 8308 PetscAssertPointer(iscoloring, 5); 8309 MatCheckPreallocated(mat, 1); 8310 8311 if (!mat->ops->coloringpatch) { 8312 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8313 } else { 8314 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8315 } 8316 PetscFunctionReturn(PETSC_SUCCESS); 8317 } 8318 8319 /*@ 8320 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8321 8322 Logically Collective 8323 8324 Input Parameter: 8325 . mat - the factored matrix to be reset 8326 8327 Level: developer 8328 8329 Notes: 8330 This routine should be used only with factored matrices formed by in-place 8331 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8332 format). This option can save memory, for example, when solving nonlinear 8333 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8334 ILU(0) preconditioner. 8335 8336 One can specify in-place ILU(0) factorization by calling 8337 .vb 8338 PCType(pc,PCILU); 8339 PCFactorSeUseInPlace(pc); 8340 .ve 8341 or by using the options -pc_type ilu -pc_factor_in_place 8342 8343 In-place factorization ILU(0) can also be used as a local 8344 solver for the blocks within the block Jacobi or additive Schwarz 8345 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8346 for details on setting local solver options. 8347 8348 Most users should employ the `KSP` interface for linear solvers 8349 instead of working directly with matrix algebra routines such as this. 8350 See, e.g., `KSPCreate()`. 8351 8352 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8353 @*/ 8354 PetscErrorCode MatSetUnfactored(Mat mat) 8355 { 8356 PetscFunctionBegin; 8357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8358 PetscValidType(mat, 1); 8359 MatCheckPreallocated(mat, 1); 8360 mat->factortype = MAT_FACTOR_NONE; 8361 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8362 PetscUseTypeMethod(mat, setunfactored); 8363 PetscFunctionReturn(PETSC_SUCCESS); 8364 } 8365 8366 /*MC 8367 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8368 8369 Synopsis: 8370 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8371 8372 Not Collective 8373 8374 Input Parameter: 8375 . x - matrix 8376 8377 Output Parameters: 8378 + xx_v - the Fortran pointer to the array 8379 - ierr - error code 8380 8381 Example of Usage: 8382 .vb 8383 PetscScalar, pointer xx_v(:,:) 8384 .... 8385 call MatDenseGetArrayF90(x,xx_v,ierr) 8386 a = xx_v(3) 8387 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8388 .ve 8389 8390 Level: advanced 8391 8392 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8393 M*/ 8394 8395 /*MC 8396 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8397 accessed with `MatDenseGetArrayF90()`. 8398 8399 Synopsis: 8400 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8401 8402 Not Collective 8403 8404 Input Parameters: 8405 + x - matrix 8406 - xx_v - the Fortran90 pointer to the array 8407 8408 Output Parameter: 8409 . ierr - error code 8410 8411 Example of Usage: 8412 .vb 8413 PetscScalar, pointer xx_v(:,:) 8414 .... 8415 call MatDenseGetArrayF90(x,xx_v,ierr) 8416 a = xx_v(3) 8417 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8418 .ve 8419 8420 Level: advanced 8421 8422 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8423 M*/ 8424 8425 /*MC 8426 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8427 8428 Synopsis: 8429 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8430 8431 Not Collective 8432 8433 Input Parameter: 8434 . x - matrix 8435 8436 Output Parameters: 8437 + xx_v - the Fortran pointer to the array 8438 - ierr - error code 8439 8440 Example of Usage: 8441 .vb 8442 PetscScalar, pointer xx_v(:) 8443 .... 8444 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8445 a = xx_v(3) 8446 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8447 .ve 8448 8449 Level: advanced 8450 8451 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8452 M*/ 8453 8454 /*MC 8455 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8456 accessed with `MatSeqAIJGetArrayF90()`. 8457 8458 Synopsis: 8459 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8460 8461 Not Collective 8462 8463 Input Parameters: 8464 + x - matrix 8465 - xx_v - the Fortran90 pointer to the array 8466 8467 Output Parameter: 8468 . ierr - error code 8469 8470 Example of Usage: 8471 .vb 8472 PetscScalar, pointer xx_v(:) 8473 .... 8474 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8475 a = xx_v(3) 8476 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8477 .ve 8478 8479 Level: advanced 8480 8481 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8482 M*/ 8483 8484 /*@ 8485 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8486 as the original matrix. 8487 8488 Collective 8489 8490 Input Parameters: 8491 + mat - the original matrix 8492 . isrow - parallel `IS` containing the rows this processor should obtain 8493 . 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. 8494 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8495 8496 Output Parameter: 8497 . newmat - the new submatrix, of the same type as the original matrix 8498 8499 Level: advanced 8500 8501 Notes: 8502 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8503 8504 Some matrix types place restrictions on the row and column indices, such 8505 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; 8506 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8507 8508 The index sets may not have duplicate entries. 8509 8510 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8511 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8512 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8513 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8514 you are finished using it. 8515 8516 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8517 the input matrix. 8518 8519 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8520 8521 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8522 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8523 8524 Example usage: 8525 Consider the following 8x8 matrix with 34 non-zero values, that is 8526 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8527 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8528 as follows 8529 .vb 8530 1 2 0 | 0 3 0 | 0 4 8531 Proc0 0 5 6 | 7 0 0 | 8 0 8532 9 0 10 | 11 0 0 | 12 0 8533 ------------------------------------- 8534 13 0 14 | 15 16 17 | 0 0 8535 Proc1 0 18 0 | 19 20 21 | 0 0 8536 0 0 0 | 22 23 0 | 24 0 8537 ------------------------------------- 8538 Proc2 25 26 27 | 0 0 28 | 29 0 8539 30 0 0 | 31 32 33 | 0 34 8540 .ve 8541 8542 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8543 8544 .vb 8545 2 0 | 0 3 0 | 0 8546 Proc0 5 6 | 7 0 0 | 8 8547 ------------------------------- 8548 Proc1 18 0 | 19 20 21 | 0 8549 ------------------------------- 8550 Proc2 26 27 | 0 0 28 | 29 8551 0 0 | 31 32 33 | 0 8552 .ve 8553 8554 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8555 @*/ 8556 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8557 { 8558 PetscMPIInt size; 8559 Mat *local; 8560 IS iscoltmp; 8561 PetscBool flg; 8562 8563 PetscFunctionBegin; 8564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8565 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8566 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8567 PetscAssertPointer(newmat, 5); 8568 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8569 PetscValidType(mat, 1); 8570 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8571 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8572 8573 MatCheckPreallocated(mat, 1); 8574 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8575 8576 if (!iscol || isrow == iscol) { 8577 PetscBool stride; 8578 PetscMPIInt grabentirematrix = 0, grab; 8579 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8580 if (stride) { 8581 PetscInt first, step, n, rstart, rend; 8582 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8583 if (step == 1) { 8584 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8585 if (rstart == first) { 8586 PetscCall(ISGetLocalSize(isrow, &n)); 8587 if (n == rend - rstart) grabentirematrix = 1; 8588 } 8589 } 8590 } 8591 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8592 if (grab) { 8593 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8594 if (cll == MAT_INITIAL_MATRIX) { 8595 *newmat = mat; 8596 PetscCall(PetscObjectReference((PetscObject)mat)); 8597 } 8598 PetscFunctionReturn(PETSC_SUCCESS); 8599 } 8600 } 8601 8602 if (!iscol) { 8603 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8604 } else { 8605 iscoltmp = iscol; 8606 } 8607 8608 /* if original matrix is on just one processor then use submatrix generated */ 8609 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8610 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8611 goto setproperties; 8612 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8613 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8614 *newmat = *local; 8615 PetscCall(PetscFree(local)); 8616 goto setproperties; 8617 } else if (!mat->ops->createsubmatrix) { 8618 /* Create a new matrix type that implements the operation using the full matrix */ 8619 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8620 switch (cll) { 8621 case MAT_INITIAL_MATRIX: 8622 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8623 break; 8624 case MAT_REUSE_MATRIX: 8625 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8626 break; 8627 default: 8628 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8629 } 8630 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8631 goto setproperties; 8632 } 8633 8634 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8635 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8636 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8637 8638 setproperties: 8639 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8640 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8641 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8642 } 8643 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8644 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8645 PetscFunctionReturn(PETSC_SUCCESS); 8646 } 8647 8648 /*@ 8649 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8650 8651 Not Collective 8652 8653 Input Parameters: 8654 + A - the matrix we wish to propagate options from 8655 - B - the matrix we wish to propagate options to 8656 8657 Level: beginner 8658 8659 Note: 8660 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8661 8662 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8663 @*/ 8664 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8665 { 8666 PetscFunctionBegin; 8667 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8668 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8669 B->symmetry_eternal = A->symmetry_eternal; 8670 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8671 B->symmetric = A->symmetric; 8672 B->structurally_symmetric = A->structurally_symmetric; 8673 B->spd = A->spd; 8674 B->hermitian = A->hermitian; 8675 PetscFunctionReturn(PETSC_SUCCESS); 8676 } 8677 8678 /*@ 8679 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8680 used during the assembly process to store values that belong to 8681 other processors. 8682 8683 Not Collective 8684 8685 Input Parameters: 8686 + mat - the matrix 8687 . size - the initial size of the stash. 8688 - bsize - the initial size of the block-stash(if used). 8689 8690 Options Database Keys: 8691 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8692 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8693 8694 Level: intermediate 8695 8696 Notes: 8697 The block-stash is used for values set with `MatSetValuesBlocked()` while 8698 the stash is used for values set with `MatSetValues()` 8699 8700 Run with the option -info and look for output of the form 8701 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8702 to determine the appropriate value, MM, to use for size and 8703 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8704 to determine the value, BMM to use for bsize 8705 8706 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8707 @*/ 8708 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8709 { 8710 PetscFunctionBegin; 8711 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8712 PetscValidType(mat, 1); 8713 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8714 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8715 PetscFunctionReturn(PETSC_SUCCESS); 8716 } 8717 8718 /*@ 8719 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8720 the matrix 8721 8722 Neighbor-wise Collective 8723 8724 Input Parameters: 8725 + A - the matrix 8726 . x - the vector to be multiplied by the interpolation operator 8727 - y - the vector to be added to the result 8728 8729 Output Parameter: 8730 . w - the resulting vector 8731 8732 Level: intermediate 8733 8734 Notes: 8735 `w` may be the same vector as `y`. 8736 8737 This allows one to use either the restriction or interpolation (its transpose) 8738 matrix to do the interpolation 8739 8740 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8741 @*/ 8742 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8743 { 8744 PetscInt M, N, Ny; 8745 8746 PetscFunctionBegin; 8747 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8748 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8749 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8750 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8751 PetscCall(MatGetSize(A, &M, &N)); 8752 PetscCall(VecGetSize(y, &Ny)); 8753 if (M == Ny) { 8754 PetscCall(MatMultAdd(A, x, y, w)); 8755 } else { 8756 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8757 } 8758 PetscFunctionReturn(PETSC_SUCCESS); 8759 } 8760 8761 /*@ 8762 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8763 the matrix 8764 8765 Neighbor-wise Collective 8766 8767 Input Parameters: 8768 + A - the matrix 8769 - x - the vector to be interpolated 8770 8771 Output Parameter: 8772 . y - the resulting vector 8773 8774 Level: intermediate 8775 8776 Note: 8777 This allows one to use either the restriction or interpolation (its transpose) 8778 matrix to do the interpolation 8779 8780 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8781 @*/ 8782 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8783 { 8784 PetscInt M, N, Ny; 8785 8786 PetscFunctionBegin; 8787 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8788 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8789 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8790 PetscCall(MatGetSize(A, &M, &N)); 8791 PetscCall(VecGetSize(y, &Ny)); 8792 if (M == Ny) { 8793 PetscCall(MatMult(A, x, y)); 8794 } else { 8795 PetscCall(MatMultTranspose(A, x, y)); 8796 } 8797 PetscFunctionReturn(PETSC_SUCCESS); 8798 } 8799 8800 /*@ 8801 MatRestrict - $y = A*x$ or $A^T*x$ 8802 8803 Neighbor-wise Collective 8804 8805 Input Parameters: 8806 + A - the matrix 8807 - x - the vector to be restricted 8808 8809 Output Parameter: 8810 . y - the resulting vector 8811 8812 Level: intermediate 8813 8814 Note: 8815 This allows one to use either the restriction or interpolation (its transpose) 8816 matrix to do the restriction 8817 8818 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8819 @*/ 8820 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8821 { 8822 PetscInt M, N, Nx; 8823 8824 PetscFunctionBegin; 8825 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8826 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8827 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8828 PetscCall(MatGetSize(A, &M, &N)); 8829 PetscCall(VecGetSize(x, &Nx)); 8830 if (M == Nx) { 8831 PetscCall(MatMultTranspose(A, x, y)); 8832 } else { 8833 PetscCall(MatMult(A, x, y)); 8834 } 8835 PetscFunctionReturn(PETSC_SUCCESS); 8836 } 8837 8838 /*@ 8839 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8840 8841 Neighbor-wise Collective 8842 8843 Input Parameters: 8844 + A - the matrix 8845 . x - the input dense matrix to be multiplied 8846 - w - the input dense matrix to be added to the result 8847 8848 Output Parameter: 8849 . y - the output dense matrix 8850 8851 Level: intermediate 8852 8853 Note: 8854 This allows one to use either the restriction or interpolation (its transpose) 8855 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8856 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8857 8858 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8859 @*/ 8860 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8861 { 8862 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8863 PetscBool trans = PETSC_TRUE; 8864 MatReuse reuse = MAT_INITIAL_MATRIX; 8865 8866 PetscFunctionBegin; 8867 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8868 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8869 PetscValidType(x, 2); 8870 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8871 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8872 PetscCall(MatGetSize(A, &M, &N)); 8873 PetscCall(MatGetSize(x, &Mx, &Nx)); 8874 if (N == Mx) trans = PETSC_FALSE; 8875 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); 8876 Mo = trans ? N : M; 8877 if (*y) { 8878 PetscCall(MatGetSize(*y, &My, &Ny)); 8879 if (Mo == My && Nx == Ny) { 8880 reuse = MAT_REUSE_MATRIX; 8881 } else { 8882 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); 8883 PetscCall(MatDestroy(y)); 8884 } 8885 } 8886 8887 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8888 PetscBool flg; 8889 8890 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8891 if (w) { 8892 PetscInt My, Ny, Mw, Nw; 8893 8894 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8895 PetscCall(MatGetSize(*y, &My, &Ny)); 8896 PetscCall(MatGetSize(w, &Mw, &Nw)); 8897 if (!flg || My != Mw || Ny != Nw) w = NULL; 8898 } 8899 if (!w) { 8900 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8901 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8902 PetscCall(PetscObjectDereference((PetscObject)w)); 8903 } else { 8904 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8905 } 8906 } 8907 if (!trans) { 8908 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8909 } else { 8910 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8911 } 8912 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8913 PetscFunctionReturn(PETSC_SUCCESS); 8914 } 8915 8916 /*@ 8917 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8918 8919 Neighbor-wise Collective 8920 8921 Input Parameters: 8922 + A - the matrix 8923 - x - the input dense matrix 8924 8925 Output Parameter: 8926 . y - the output dense matrix 8927 8928 Level: intermediate 8929 8930 Note: 8931 This allows one to use either the restriction or interpolation (its transpose) 8932 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8933 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8934 8935 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8936 @*/ 8937 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8938 { 8939 PetscFunctionBegin; 8940 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8941 PetscFunctionReturn(PETSC_SUCCESS); 8942 } 8943 8944 /*@ 8945 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8946 8947 Neighbor-wise Collective 8948 8949 Input Parameters: 8950 + A - the matrix 8951 - x - the input dense matrix 8952 8953 Output Parameter: 8954 . y - the output dense matrix 8955 8956 Level: intermediate 8957 8958 Note: 8959 This allows one to use either the restriction or interpolation (its transpose) 8960 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8961 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8962 8963 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8964 @*/ 8965 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8966 { 8967 PetscFunctionBegin; 8968 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8969 PetscFunctionReturn(PETSC_SUCCESS); 8970 } 8971 8972 /*@ 8973 MatGetNullSpace - retrieves the null space of a matrix. 8974 8975 Logically Collective 8976 8977 Input Parameters: 8978 + mat - the matrix 8979 - nullsp - the null space object 8980 8981 Level: developer 8982 8983 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8984 @*/ 8985 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8986 { 8987 PetscFunctionBegin; 8988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8989 PetscAssertPointer(nullsp, 2); 8990 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8991 PetscFunctionReturn(PETSC_SUCCESS); 8992 } 8993 8994 /*@C 8995 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8996 8997 Logically Collective 8998 8999 Input Parameters: 9000 + n - the number of matrices 9001 - mat - the array of matrices 9002 9003 Output Parameters: 9004 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9005 9006 Level: developer 9007 9008 Note: 9009 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9010 9011 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9012 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9013 @*/ 9014 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9015 { 9016 PetscFunctionBegin; 9017 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9018 PetscAssertPointer(mat, 2); 9019 PetscAssertPointer(nullsp, 3); 9020 9021 PetscCall(PetscCalloc1(3 * n, nullsp)); 9022 for (PetscInt i = 0; i < n; i++) { 9023 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9024 (*nullsp)[i] = mat[i]->nullsp; 9025 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9026 (*nullsp)[n + i] = mat[i]->nearnullsp; 9027 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9028 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9029 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9030 } 9031 PetscFunctionReturn(PETSC_SUCCESS); 9032 } 9033 9034 /*@C 9035 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9036 9037 Logically Collective 9038 9039 Input Parameters: 9040 + n - the number of matrices 9041 . mat - the array of matrices 9042 - nullsp - an array of null spaces 9043 9044 Level: developer 9045 9046 Note: 9047 Call `MatGetNullSpaces()` to create `nullsp` 9048 9049 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9050 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9051 @*/ 9052 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9053 { 9054 PetscFunctionBegin; 9055 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9056 PetscAssertPointer(mat, 2); 9057 PetscAssertPointer(nullsp, 3); 9058 PetscAssertPointer(*nullsp, 3); 9059 9060 for (PetscInt i = 0; i < n; i++) { 9061 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9062 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9063 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9064 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9065 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9066 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9067 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9068 } 9069 PetscCall(PetscFree(*nullsp)); 9070 PetscFunctionReturn(PETSC_SUCCESS); 9071 } 9072 9073 /*@ 9074 MatSetNullSpace - attaches a null space to a matrix. 9075 9076 Logically Collective 9077 9078 Input Parameters: 9079 + mat - the matrix 9080 - nullsp - the null space object 9081 9082 Level: advanced 9083 9084 Notes: 9085 This null space is used by the `KSP` linear solvers to solve singular systems. 9086 9087 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` 9088 9089 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 9090 to zero but the linear system will still be solved in a least squares sense. 9091 9092 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9093 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)$. 9094 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 9095 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 9096 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$). 9097 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9098 9099 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9100 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9101 routine also automatically calls `MatSetTransposeNullSpace()`. 9102 9103 The user should call `MatNullSpaceDestroy()`. 9104 9105 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9106 `KSPSetPCSide()` 9107 @*/ 9108 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9109 { 9110 PetscFunctionBegin; 9111 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9112 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9113 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9114 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9115 mat->nullsp = nullsp; 9116 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9117 PetscFunctionReturn(PETSC_SUCCESS); 9118 } 9119 9120 /*@ 9121 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9122 9123 Logically Collective 9124 9125 Input Parameters: 9126 + mat - the matrix 9127 - nullsp - the null space object 9128 9129 Level: developer 9130 9131 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9132 @*/ 9133 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9134 { 9135 PetscFunctionBegin; 9136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9137 PetscValidType(mat, 1); 9138 PetscAssertPointer(nullsp, 2); 9139 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9140 PetscFunctionReturn(PETSC_SUCCESS); 9141 } 9142 9143 /*@ 9144 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9145 9146 Logically Collective 9147 9148 Input Parameters: 9149 + mat - the matrix 9150 - nullsp - the null space object 9151 9152 Level: advanced 9153 9154 Notes: 9155 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9156 9157 See `MatSetNullSpace()` 9158 9159 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9160 @*/ 9161 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9162 { 9163 PetscFunctionBegin; 9164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9165 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9166 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9167 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9168 mat->transnullsp = nullsp; 9169 PetscFunctionReturn(PETSC_SUCCESS); 9170 } 9171 9172 /*@ 9173 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9174 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9175 9176 Logically Collective 9177 9178 Input Parameters: 9179 + mat - the matrix 9180 - nullsp - the null space object 9181 9182 Level: advanced 9183 9184 Notes: 9185 Overwrites any previous near null space that may have been attached 9186 9187 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9188 9189 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9190 @*/ 9191 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9192 { 9193 PetscFunctionBegin; 9194 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9195 PetscValidType(mat, 1); 9196 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9197 MatCheckPreallocated(mat, 1); 9198 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9199 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9200 mat->nearnullsp = nullsp; 9201 PetscFunctionReturn(PETSC_SUCCESS); 9202 } 9203 9204 /*@ 9205 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9206 9207 Not Collective 9208 9209 Input Parameter: 9210 . mat - the matrix 9211 9212 Output Parameter: 9213 . nullsp - the null space object, `NULL` if not set 9214 9215 Level: advanced 9216 9217 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9218 @*/ 9219 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9220 { 9221 PetscFunctionBegin; 9222 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9223 PetscValidType(mat, 1); 9224 PetscAssertPointer(nullsp, 2); 9225 MatCheckPreallocated(mat, 1); 9226 *nullsp = mat->nearnullsp; 9227 PetscFunctionReturn(PETSC_SUCCESS); 9228 } 9229 9230 /*@ 9231 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9232 9233 Collective 9234 9235 Input Parameters: 9236 + mat - the matrix 9237 . row - row/column permutation 9238 - info - information on desired factorization process 9239 9240 Level: developer 9241 9242 Notes: 9243 Probably really in-place only when level of fill is zero, otherwise allocates 9244 new space to store factored matrix and deletes previous memory. 9245 9246 Most users should employ the `KSP` interface for linear solvers 9247 instead of working directly with matrix algebra routines such as this. 9248 See, e.g., `KSPCreate()`. 9249 9250 Developer Note: 9251 The Fortran interface is not autogenerated as the 9252 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9253 9254 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9255 @*/ 9256 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9257 { 9258 PetscFunctionBegin; 9259 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9260 PetscValidType(mat, 1); 9261 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9262 PetscAssertPointer(info, 3); 9263 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9265 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9266 MatCheckPreallocated(mat, 1); 9267 PetscUseTypeMethod(mat, iccfactor, row, info); 9268 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9269 PetscFunctionReturn(PETSC_SUCCESS); 9270 } 9271 9272 /*@ 9273 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9274 ghosted ones. 9275 9276 Not Collective 9277 9278 Input Parameters: 9279 + mat - the matrix 9280 - diag - the diagonal values, including ghost ones 9281 9282 Level: developer 9283 9284 Notes: 9285 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9286 9287 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9288 9289 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9290 @*/ 9291 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9292 { 9293 PetscMPIInt size; 9294 9295 PetscFunctionBegin; 9296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9297 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9298 PetscValidType(mat, 1); 9299 9300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9301 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9302 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9303 if (size == 1) { 9304 PetscInt n, m; 9305 PetscCall(VecGetSize(diag, &n)); 9306 PetscCall(MatGetSize(mat, NULL, &m)); 9307 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9308 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9309 } else { 9310 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9311 } 9312 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9313 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9314 PetscFunctionReturn(PETSC_SUCCESS); 9315 } 9316 9317 /*@ 9318 MatGetInertia - Gets the inertia from a factored matrix 9319 9320 Collective 9321 9322 Input Parameter: 9323 . mat - the matrix 9324 9325 Output Parameters: 9326 + nneg - number of negative eigenvalues 9327 . nzero - number of zero eigenvalues 9328 - npos - number of positive eigenvalues 9329 9330 Level: advanced 9331 9332 Note: 9333 Matrix must have been factored by `MatCholeskyFactor()` 9334 9335 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9336 @*/ 9337 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9338 { 9339 PetscFunctionBegin; 9340 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9341 PetscValidType(mat, 1); 9342 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9343 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9344 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9345 PetscFunctionReturn(PETSC_SUCCESS); 9346 } 9347 9348 /*@C 9349 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9350 9351 Neighbor-wise Collective 9352 9353 Input Parameters: 9354 + mat - the factored matrix obtained with `MatGetFactor()` 9355 - b - the right-hand-side vectors 9356 9357 Output Parameter: 9358 . x - the result vectors 9359 9360 Level: developer 9361 9362 Note: 9363 The vectors `b` and `x` cannot be the same. I.e., one cannot 9364 call `MatSolves`(A,x,x). 9365 9366 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9367 @*/ 9368 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9369 { 9370 PetscFunctionBegin; 9371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9372 PetscValidType(mat, 1); 9373 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9374 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9375 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9376 9377 MatCheckPreallocated(mat, 1); 9378 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9379 PetscUseTypeMethod(mat, solves, b, x); 9380 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9381 PetscFunctionReturn(PETSC_SUCCESS); 9382 } 9383 9384 /*@ 9385 MatIsSymmetric - Test whether a matrix is symmetric 9386 9387 Collective 9388 9389 Input Parameters: 9390 + A - the matrix to test 9391 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9392 9393 Output Parameter: 9394 . flg - the result 9395 9396 Level: intermediate 9397 9398 Notes: 9399 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9400 9401 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9402 9403 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9404 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9405 9406 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9407 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9408 @*/ 9409 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9410 { 9411 PetscFunctionBegin; 9412 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9413 PetscAssertPointer(flg, 3); 9414 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9415 else { 9416 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9417 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9418 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9419 } 9420 PetscFunctionReturn(PETSC_SUCCESS); 9421 } 9422 9423 /*@ 9424 MatIsHermitian - Test whether a matrix is Hermitian 9425 9426 Collective 9427 9428 Input Parameters: 9429 + A - the matrix to test 9430 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9431 9432 Output Parameter: 9433 . flg - the result 9434 9435 Level: intermediate 9436 9437 Notes: 9438 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9439 9440 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9441 9442 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9443 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9444 9445 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9446 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9447 @*/ 9448 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9449 { 9450 PetscFunctionBegin; 9451 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9452 PetscAssertPointer(flg, 3); 9453 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9454 else { 9455 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9456 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9457 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9458 } 9459 PetscFunctionReturn(PETSC_SUCCESS); 9460 } 9461 9462 /*@ 9463 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9464 9465 Not Collective 9466 9467 Input Parameter: 9468 . A - the matrix to check 9469 9470 Output Parameters: 9471 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9472 - flg - the result (only valid if set is `PETSC_TRUE`) 9473 9474 Level: advanced 9475 9476 Notes: 9477 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9478 if you want it explicitly checked 9479 9480 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9481 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9482 9483 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9484 @*/ 9485 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9486 { 9487 PetscFunctionBegin; 9488 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9489 PetscAssertPointer(set, 2); 9490 PetscAssertPointer(flg, 3); 9491 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9492 *set = PETSC_TRUE; 9493 *flg = PetscBool3ToBool(A->symmetric); 9494 } else { 9495 *set = PETSC_FALSE; 9496 } 9497 PetscFunctionReturn(PETSC_SUCCESS); 9498 } 9499 9500 /*@ 9501 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9502 9503 Not Collective 9504 9505 Input Parameter: 9506 . A - the matrix to check 9507 9508 Output Parameters: 9509 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9510 - flg - the result (only valid if set is `PETSC_TRUE`) 9511 9512 Level: advanced 9513 9514 Notes: 9515 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9516 9517 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9518 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9519 9520 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9521 @*/ 9522 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9523 { 9524 PetscFunctionBegin; 9525 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9526 PetscAssertPointer(set, 2); 9527 PetscAssertPointer(flg, 3); 9528 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9529 *set = PETSC_TRUE; 9530 *flg = PetscBool3ToBool(A->spd); 9531 } else { 9532 *set = PETSC_FALSE; 9533 } 9534 PetscFunctionReturn(PETSC_SUCCESS); 9535 } 9536 9537 /*@ 9538 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9539 9540 Not Collective 9541 9542 Input Parameter: 9543 . A - the matrix to check 9544 9545 Output Parameters: 9546 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9547 - flg - the result (only valid if set is `PETSC_TRUE`) 9548 9549 Level: advanced 9550 9551 Notes: 9552 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9553 if you want it explicitly checked 9554 9555 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9556 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9557 9558 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9559 @*/ 9560 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9561 { 9562 PetscFunctionBegin; 9563 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9564 PetscAssertPointer(set, 2); 9565 PetscAssertPointer(flg, 3); 9566 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9567 *set = PETSC_TRUE; 9568 *flg = PetscBool3ToBool(A->hermitian); 9569 } else { 9570 *set = PETSC_FALSE; 9571 } 9572 PetscFunctionReturn(PETSC_SUCCESS); 9573 } 9574 9575 /*@ 9576 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9577 9578 Collective 9579 9580 Input Parameter: 9581 . A - the matrix to test 9582 9583 Output Parameter: 9584 . flg - the result 9585 9586 Level: intermediate 9587 9588 Notes: 9589 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9590 9591 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 9592 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9593 9594 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9595 @*/ 9596 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9597 { 9598 PetscFunctionBegin; 9599 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9600 PetscAssertPointer(flg, 2); 9601 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9602 *flg = PetscBool3ToBool(A->structurally_symmetric); 9603 } else { 9604 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9605 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9606 } 9607 PetscFunctionReturn(PETSC_SUCCESS); 9608 } 9609 9610 /*@ 9611 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9612 9613 Not Collective 9614 9615 Input Parameter: 9616 . A - the matrix to check 9617 9618 Output Parameters: 9619 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9620 - flg - the result (only valid if set is PETSC_TRUE) 9621 9622 Level: advanced 9623 9624 Notes: 9625 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 9626 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9627 9628 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9629 9630 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9631 @*/ 9632 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9633 { 9634 PetscFunctionBegin; 9635 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9636 PetscAssertPointer(set, 2); 9637 PetscAssertPointer(flg, 3); 9638 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9639 *set = PETSC_TRUE; 9640 *flg = PetscBool3ToBool(A->structurally_symmetric); 9641 } else { 9642 *set = PETSC_FALSE; 9643 } 9644 PetscFunctionReturn(PETSC_SUCCESS); 9645 } 9646 9647 /*@ 9648 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9649 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9650 9651 Not Collective 9652 9653 Input Parameter: 9654 . mat - the matrix 9655 9656 Output Parameters: 9657 + nstash - the size of the stash 9658 . reallocs - the number of additional mallocs incurred. 9659 . bnstash - the size of the block stash 9660 - breallocs - the number of additional mallocs incurred.in the block stash 9661 9662 Level: advanced 9663 9664 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9665 @*/ 9666 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9667 { 9668 PetscFunctionBegin; 9669 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9670 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9671 PetscFunctionReturn(PETSC_SUCCESS); 9672 } 9673 9674 /*@ 9675 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9676 parallel layout, `PetscLayout` for rows and columns 9677 9678 Collective 9679 9680 Input Parameter: 9681 . mat - the matrix 9682 9683 Output Parameters: 9684 + right - (optional) vector that the matrix can be multiplied against 9685 - left - (optional) vector that the matrix vector product can be stored in 9686 9687 Level: advanced 9688 9689 Notes: 9690 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()`. 9691 9692 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9693 9694 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9695 @*/ 9696 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9697 { 9698 PetscFunctionBegin; 9699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9700 PetscValidType(mat, 1); 9701 if (mat->ops->getvecs) { 9702 PetscUseTypeMethod(mat, getvecs, right, left); 9703 } else { 9704 if (right) { 9705 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9706 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9707 PetscCall(VecSetType(*right, mat->defaultvectype)); 9708 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9709 if (mat->boundtocpu && mat->bindingpropagates) { 9710 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9711 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9712 } 9713 #endif 9714 } 9715 if (left) { 9716 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9717 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9718 PetscCall(VecSetType(*left, mat->defaultvectype)); 9719 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9720 if (mat->boundtocpu && mat->bindingpropagates) { 9721 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9722 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9723 } 9724 #endif 9725 } 9726 } 9727 PetscFunctionReturn(PETSC_SUCCESS); 9728 } 9729 9730 /*@ 9731 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9732 with default values. 9733 9734 Not Collective 9735 9736 Input Parameter: 9737 . info - the `MatFactorInfo` data structure 9738 9739 Level: developer 9740 9741 Notes: 9742 The solvers are generally used through the `KSP` and `PC` objects, for example 9743 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9744 9745 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9746 9747 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9748 @*/ 9749 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9750 { 9751 PetscFunctionBegin; 9752 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9753 PetscFunctionReturn(PETSC_SUCCESS); 9754 } 9755 9756 /*@ 9757 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9758 9759 Collective 9760 9761 Input Parameters: 9762 + mat - the factored matrix 9763 - is - the index set defining the Schur indices (0-based) 9764 9765 Level: advanced 9766 9767 Notes: 9768 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9769 9770 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9771 9772 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9773 9774 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9775 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9776 @*/ 9777 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9778 { 9779 PetscErrorCode (*f)(Mat, IS); 9780 9781 PetscFunctionBegin; 9782 PetscValidType(mat, 1); 9783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9784 PetscValidType(is, 2); 9785 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9786 PetscCheckSameComm(mat, 1, is, 2); 9787 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9788 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9789 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9790 PetscCall(MatDestroy(&mat->schur)); 9791 PetscCall((*f)(mat, is)); 9792 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9793 PetscFunctionReturn(PETSC_SUCCESS); 9794 } 9795 9796 /*@ 9797 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9798 9799 Logically Collective 9800 9801 Input Parameters: 9802 + F - the factored matrix obtained by calling `MatGetFactor()` 9803 . S - location where to return the Schur complement, can be `NULL` 9804 - status - the status of the Schur complement matrix, can be `NULL` 9805 9806 Level: advanced 9807 9808 Notes: 9809 You must call `MatFactorSetSchurIS()` before calling this routine. 9810 9811 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9812 9813 The routine provides a copy of the Schur matrix stored within the solver data structures. 9814 The caller must destroy the object when it is no longer needed. 9815 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9816 9817 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) 9818 9819 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9820 9821 Developer Note: 9822 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9823 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9824 9825 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9826 @*/ 9827 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9828 { 9829 PetscFunctionBegin; 9830 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9831 if (S) PetscAssertPointer(S, 2); 9832 if (status) PetscAssertPointer(status, 3); 9833 if (S) { 9834 PetscErrorCode (*f)(Mat, Mat *); 9835 9836 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9837 if (f) { 9838 PetscCall((*f)(F, S)); 9839 } else { 9840 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9841 } 9842 } 9843 if (status) *status = F->schur_status; 9844 PetscFunctionReturn(PETSC_SUCCESS); 9845 } 9846 9847 /*@ 9848 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9849 9850 Logically Collective 9851 9852 Input Parameters: 9853 + F - the factored matrix obtained by calling `MatGetFactor()` 9854 . S - location where to return the Schur complement, can be `NULL` 9855 - status - the status of the Schur complement matrix, can be `NULL` 9856 9857 Level: advanced 9858 9859 Notes: 9860 You must call `MatFactorSetSchurIS()` before calling this routine. 9861 9862 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9863 9864 The routine returns a the Schur Complement stored within the data structures of the solver. 9865 9866 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9867 9868 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9869 9870 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9871 9872 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9873 9874 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9875 @*/ 9876 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9877 { 9878 PetscFunctionBegin; 9879 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9880 if (S) { 9881 PetscAssertPointer(S, 2); 9882 *S = F->schur; 9883 } 9884 if (status) { 9885 PetscAssertPointer(status, 3); 9886 *status = F->schur_status; 9887 } 9888 PetscFunctionReturn(PETSC_SUCCESS); 9889 } 9890 9891 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9892 { 9893 Mat S = F->schur; 9894 9895 PetscFunctionBegin; 9896 switch (F->schur_status) { 9897 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9898 case MAT_FACTOR_SCHUR_INVERTED: 9899 if (S) { 9900 S->ops->solve = NULL; 9901 S->ops->matsolve = NULL; 9902 S->ops->solvetranspose = NULL; 9903 S->ops->matsolvetranspose = NULL; 9904 S->ops->solveadd = NULL; 9905 S->ops->solvetransposeadd = NULL; 9906 S->factortype = MAT_FACTOR_NONE; 9907 PetscCall(PetscFree(S->solvertype)); 9908 } 9909 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9910 break; 9911 default: 9912 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9913 } 9914 PetscFunctionReturn(PETSC_SUCCESS); 9915 } 9916 9917 /*@ 9918 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9919 9920 Logically Collective 9921 9922 Input Parameters: 9923 + F - the factored matrix obtained by calling `MatGetFactor()` 9924 . S - location where the Schur complement is stored 9925 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9926 9927 Level: advanced 9928 9929 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9930 @*/ 9931 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9932 { 9933 PetscFunctionBegin; 9934 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9935 if (S) { 9936 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9937 *S = NULL; 9938 } 9939 F->schur_status = status; 9940 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9941 PetscFunctionReturn(PETSC_SUCCESS); 9942 } 9943 9944 /*@ 9945 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9946 9947 Logically Collective 9948 9949 Input Parameters: 9950 + F - the factored matrix obtained by calling `MatGetFactor()` 9951 . rhs - location where the right-hand side of the Schur complement system is stored 9952 - sol - location where the solution of the Schur complement system has to be returned 9953 9954 Level: advanced 9955 9956 Notes: 9957 The sizes of the vectors should match the size of the Schur complement 9958 9959 Must be called after `MatFactorSetSchurIS()` 9960 9961 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9962 @*/ 9963 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9964 { 9965 PetscFunctionBegin; 9966 PetscValidType(F, 1); 9967 PetscValidType(rhs, 2); 9968 PetscValidType(sol, 3); 9969 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9970 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9971 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9972 PetscCheckSameComm(F, 1, rhs, 2); 9973 PetscCheckSameComm(F, 1, sol, 3); 9974 PetscCall(MatFactorFactorizeSchurComplement(F)); 9975 switch (F->schur_status) { 9976 case MAT_FACTOR_SCHUR_FACTORED: 9977 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9978 break; 9979 case MAT_FACTOR_SCHUR_INVERTED: 9980 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9981 break; 9982 default: 9983 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9984 } 9985 PetscFunctionReturn(PETSC_SUCCESS); 9986 } 9987 9988 /*@ 9989 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9990 9991 Logically Collective 9992 9993 Input Parameters: 9994 + F - the factored matrix obtained by calling `MatGetFactor()` 9995 . rhs - location where the right-hand side of the Schur complement system is stored 9996 - sol - location where the solution of the Schur complement system has to be returned 9997 9998 Level: advanced 9999 10000 Notes: 10001 The sizes of the vectors should match the size of the Schur complement 10002 10003 Must be called after `MatFactorSetSchurIS()` 10004 10005 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10006 @*/ 10007 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10008 { 10009 PetscFunctionBegin; 10010 PetscValidType(F, 1); 10011 PetscValidType(rhs, 2); 10012 PetscValidType(sol, 3); 10013 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10014 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10015 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10016 PetscCheckSameComm(F, 1, rhs, 2); 10017 PetscCheckSameComm(F, 1, sol, 3); 10018 PetscCall(MatFactorFactorizeSchurComplement(F)); 10019 switch (F->schur_status) { 10020 case MAT_FACTOR_SCHUR_FACTORED: 10021 PetscCall(MatSolve(F->schur, rhs, sol)); 10022 break; 10023 case MAT_FACTOR_SCHUR_INVERTED: 10024 PetscCall(MatMult(F->schur, rhs, sol)); 10025 break; 10026 default: 10027 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10028 } 10029 PetscFunctionReturn(PETSC_SUCCESS); 10030 } 10031 10032 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10033 #if PetscDefined(HAVE_CUDA) 10034 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10035 #endif 10036 10037 /* Schur status updated in the interface */ 10038 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10039 { 10040 Mat S = F->schur; 10041 10042 PetscFunctionBegin; 10043 if (S) { 10044 PetscMPIInt size; 10045 PetscBool isdense, isdensecuda; 10046 10047 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10048 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10049 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10050 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10051 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10052 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10053 if (isdense) { 10054 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10055 } else if (isdensecuda) { 10056 #if defined(PETSC_HAVE_CUDA) 10057 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10058 #endif 10059 } 10060 // HIP?????????????? 10061 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10062 } 10063 PetscFunctionReturn(PETSC_SUCCESS); 10064 } 10065 10066 /*@ 10067 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10068 10069 Logically Collective 10070 10071 Input Parameter: 10072 . F - the factored matrix obtained by calling `MatGetFactor()` 10073 10074 Level: advanced 10075 10076 Notes: 10077 Must be called after `MatFactorSetSchurIS()`. 10078 10079 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10080 10081 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10082 @*/ 10083 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10084 { 10085 PetscFunctionBegin; 10086 PetscValidType(F, 1); 10087 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10088 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10089 PetscCall(MatFactorFactorizeSchurComplement(F)); 10090 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10091 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10092 PetscFunctionReturn(PETSC_SUCCESS); 10093 } 10094 10095 /*@ 10096 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10097 10098 Logically Collective 10099 10100 Input Parameter: 10101 . F - the factored matrix obtained by calling `MatGetFactor()` 10102 10103 Level: advanced 10104 10105 Note: 10106 Must be called after `MatFactorSetSchurIS()` 10107 10108 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10109 @*/ 10110 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10111 { 10112 MatFactorInfo info; 10113 10114 PetscFunctionBegin; 10115 PetscValidType(F, 1); 10116 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10117 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10118 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10119 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10120 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10121 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10122 } else { 10123 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10124 } 10125 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10126 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10127 PetscFunctionReturn(PETSC_SUCCESS); 10128 } 10129 10130 /*@ 10131 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10132 10133 Neighbor-wise Collective 10134 10135 Input Parameters: 10136 + A - the matrix 10137 . P - the projection matrix 10138 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10139 - 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 10140 if the result is a dense matrix this is irrelevant 10141 10142 Output Parameter: 10143 . C - the product matrix 10144 10145 Level: intermediate 10146 10147 Notes: 10148 C will be created and must be destroyed by the user with `MatDestroy()`. 10149 10150 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10151 10152 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10153 10154 Developer Note: 10155 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10156 10157 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10158 @*/ 10159 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10160 { 10161 PetscFunctionBegin; 10162 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10163 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10164 10165 if (scall == MAT_INITIAL_MATRIX) { 10166 PetscCall(MatProductCreate(A, P, NULL, C)); 10167 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10168 PetscCall(MatProductSetAlgorithm(*C, "default")); 10169 PetscCall(MatProductSetFill(*C, fill)); 10170 10171 (*C)->product->api_user = PETSC_TRUE; 10172 PetscCall(MatProductSetFromOptions(*C)); 10173 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); 10174 PetscCall(MatProductSymbolic(*C)); 10175 } else { /* scall == MAT_REUSE_MATRIX */ 10176 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10177 } 10178 10179 PetscCall(MatProductNumeric(*C)); 10180 (*C)->symmetric = A->symmetric; 10181 (*C)->spd = A->spd; 10182 PetscFunctionReturn(PETSC_SUCCESS); 10183 } 10184 10185 /*@ 10186 MatRARt - Creates the matrix product $C = R * A * R^T$ 10187 10188 Neighbor-wise Collective 10189 10190 Input Parameters: 10191 + A - the matrix 10192 . R - the projection matrix 10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10194 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10195 if the result is a dense matrix this is irrelevant 10196 10197 Output Parameter: 10198 . C - the product matrix 10199 10200 Level: intermediate 10201 10202 Notes: 10203 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10204 10205 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10206 10207 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10208 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10209 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10210 We recommend using `MatPtAP()` when possible. 10211 10212 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10213 10214 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10215 @*/ 10216 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10217 { 10218 PetscFunctionBegin; 10219 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10220 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10221 10222 if (scall == MAT_INITIAL_MATRIX) { 10223 PetscCall(MatProductCreate(A, R, NULL, C)); 10224 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10225 PetscCall(MatProductSetAlgorithm(*C, "default")); 10226 PetscCall(MatProductSetFill(*C, fill)); 10227 10228 (*C)->product->api_user = PETSC_TRUE; 10229 PetscCall(MatProductSetFromOptions(*C)); 10230 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); 10231 PetscCall(MatProductSymbolic(*C)); 10232 } else { /* scall == MAT_REUSE_MATRIX */ 10233 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10234 } 10235 10236 PetscCall(MatProductNumeric(*C)); 10237 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10238 PetscFunctionReturn(PETSC_SUCCESS); 10239 } 10240 10241 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10242 { 10243 PetscBool flg = PETSC_TRUE; 10244 10245 PetscFunctionBegin; 10246 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10247 if (scall == MAT_INITIAL_MATRIX) { 10248 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10249 PetscCall(MatProductCreate(A, B, NULL, C)); 10250 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10251 PetscCall(MatProductSetFill(*C, fill)); 10252 } else { /* scall == MAT_REUSE_MATRIX */ 10253 Mat_Product *product = (*C)->product; 10254 10255 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10256 if (flg && product && product->type != ptype) { 10257 PetscCall(MatProductClear(*C)); 10258 product = NULL; 10259 } 10260 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10261 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10262 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10263 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10264 product = (*C)->product; 10265 product->fill = fill; 10266 product->clear = PETSC_TRUE; 10267 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10268 flg = PETSC_FALSE; 10269 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10270 } 10271 } 10272 if (flg) { 10273 (*C)->product->api_user = PETSC_TRUE; 10274 PetscCall(MatProductSetType(*C, ptype)); 10275 PetscCall(MatProductSetFromOptions(*C)); 10276 PetscCall(MatProductSymbolic(*C)); 10277 } 10278 PetscCall(MatProductNumeric(*C)); 10279 PetscFunctionReturn(PETSC_SUCCESS); 10280 } 10281 10282 /*@ 10283 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10284 10285 Neighbor-wise Collective 10286 10287 Input Parameters: 10288 + A - the left matrix 10289 . B - the right matrix 10290 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10291 - 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 10292 if the result is a dense matrix this is irrelevant 10293 10294 Output Parameter: 10295 . C - the product matrix 10296 10297 Notes: 10298 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10299 10300 `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 10301 call to this function with `MAT_INITIAL_MATRIX`. 10302 10303 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10304 10305 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`, 10306 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10307 10308 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10309 10310 Example of Usage: 10311 .vb 10312 MatProductCreate(A,B,NULL,&C); 10313 MatProductSetType(C,MATPRODUCT_AB); 10314 MatProductSymbolic(C); 10315 MatProductNumeric(C); // compute C=A * B 10316 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10317 MatProductNumeric(C); 10318 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10319 MatProductNumeric(C); 10320 .ve 10321 10322 Level: intermediate 10323 10324 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10325 @*/ 10326 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10327 { 10328 PetscFunctionBegin; 10329 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10330 PetscFunctionReturn(PETSC_SUCCESS); 10331 } 10332 10333 /*@ 10334 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10335 10336 Neighbor-wise Collective 10337 10338 Input Parameters: 10339 + A - the left matrix 10340 . B - the right matrix 10341 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10342 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10343 10344 Output Parameter: 10345 . C - the product matrix 10346 10347 Options Database Key: 10348 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10349 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10350 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10351 10352 Level: intermediate 10353 10354 Notes: 10355 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10356 10357 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10358 10359 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10360 actually needed. 10361 10362 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10363 and for pairs of `MATMPIDENSE` matrices. 10364 10365 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10366 10367 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10368 10369 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10370 @*/ 10371 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10372 { 10373 PetscFunctionBegin; 10374 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10375 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10376 PetscFunctionReturn(PETSC_SUCCESS); 10377 } 10378 10379 /*@ 10380 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10381 10382 Neighbor-wise Collective 10383 10384 Input Parameters: 10385 + A - the left matrix 10386 . B - the right matrix 10387 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10388 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10389 10390 Output Parameter: 10391 . C - the product matrix 10392 10393 Level: intermediate 10394 10395 Notes: 10396 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10397 10398 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10399 10400 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10401 10402 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10403 actually needed. 10404 10405 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10406 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10407 10408 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10409 10410 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10411 @*/ 10412 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10413 { 10414 PetscFunctionBegin; 10415 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10416 PetscFunctionReturn(PETSC_SUCCESS); 10417 } 10418 10419 /*@ 10420 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10421 10422 Neighbor-wise Collective 10423 10424 Input Parameters: 10425 + A - the left matrix 10426 . B - the middle matrix 10427 . C - the right matrix 10428 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10429 - 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 10430 if the result is a dense matrix this is irrelevant 10431 10432 Output Parameter: 10433 . D - the product matrix 10434 10435 Level: intermediate 10436 10437 Notes: 10438 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10439 10440 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10441 10442 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10443 10444 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10445 actually needed. 10446 10447 If you have many matrices with the same non-zero structure to multiply, you 10448 should use `MAT_REUSE_MATRIX` in all calls but the first 10449 10450 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10451 10452 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10453 @*/ 10454 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10455 { 10456 PetscFunctionBegin; 10457 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10458 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10459 10460 if (scall == MAT_INITIAL_MATRIX) { 10461 PetscCall(MatProductCreate(A, B, C, D)); 10462 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10463 PetscCall(MatProductSetAlgorithm(*D, "default")); 10464 PetscCall(MatProductSetFill(*D, fill)); 10465 10466 (*D)->product->api_user = PETSC_TRUE; 10467 PetscCall(MatProductSetFromOptions(*D)); 10468 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, 10469 ((PetscObject)C)->type_name); 10470 PetscCall(MatProductSymbolic(*D)); 10471 } else { /* user may change input matrices when REUSE */ 10472 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10473 } 10474 PetscCall(MatProductNumeric(*D)); 10475 PetscFunctionReturn(PETSC_SUCCESS); 10476 } 10477 10478 /*@ 10479 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10480 10481 Collective 10482 10483 Input Parameters: 10484 + mat - the matrix 10485 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10486 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10487 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10488 10489 Output Parameter: 10490 . matredundant - redundant matrix 10491 10492 Level: advanced 10493 10494 Notes: 10495 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10496 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10497 10498 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10499 calling it. 10500 10501 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10502 10503 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10504 @*/ 10505 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10506 { 10507 MPI_Comm comm; 10508 PetscMPIInt size; 10509 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10510 Mat_Redundant *redund = NULL; 10511 PetscSubcomm psubcomm = NULL; 10512 MPI_Comm subcomm_in = subcomm; 10513 Mat *matseq; 10514 IS isrow, iscol; 10515 PetscBool newsubcomm = PETSC_FALSE; 10516 10517 PetscFunctionBegin; 10518 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10519 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10520 PetscAssertPointer(*matredundant, 5); 10521 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10522 } 10523 10524 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10525 if (size == 1 || nsubcomm == 1) { 10526 if (reuse == MAT_INITIAL_MATRIX) { 10527 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10528 } else { 10529 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"); 10530 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10531 } 10532 PetscFunctionReturn(PETSC_SUCCESS); 10533 } 10534 10535 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10536 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10537 MatCheckPreallocated(mat, 1); 10538 10539 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10540 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10541 /* create psubcomm, then get subcomm */ 10542 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10543 PetscCallMPI(MPI_Comm_size(comm, &size)); 10544 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10545 10546 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10547 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10548 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10549 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10550 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10551 newsubcomm = PETSC_TRUE; 10552 PetscCall(PetscSubcommDestroy(&psubcomm)); 10553 } 10554 10555 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10556 if (reuse == MAT_INITIAL_MATRIX) { 10557 mloc_sub = PETSC_DECIDE; 10558 nloc_sub = PETSC_DECIDE; 10559 if (bs < 1) { 10560 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10561 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10562 } else { 10563 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10564 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10565 } 10566 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10567 rstart = rend - mloc_sub; 10568 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10569 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10570 PetscCall(ISSetIdentity(iscol)); 10571 } else { /* reuse == MAT_REUSE_MATRIX */ 10572 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"); 10573 /* retrieve subcomm */ 10574 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10575 redund = (*matredundant)->redundant; 10576 isrow = redund->isrow; 10577 iscol = redund->iscol; 10578 matseq = redund->matseq; 10579 } 10580 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10581 10582 /* get matredundant over subcomm */ 10583 if (reuse == MAT_INITIAL_MATRIX) { 10584 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10585 10586 /* create a supporting struct and attach it to C for reuse */ 10587 PetscCall(PetscNew(&redund)); 10588 (*matredundant)->redundant = redund; 10589 redund->isrow = isrow; 10590 redund->iscol = iscol; 10591 redund->matseq = matseq; 10592 if (newsubcomm) { 10593 redund->subcomm = subcomm; 10594 } else { 10595 redund->subcomm = MPI_COMM_NULL; 10596 } 10597 } else { 10598 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10599 } 10600 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10601 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10602 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10603 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10604 } 10605 #endif 10606 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10607 PetscFunctionReturn(PETSC_SUCCESS); 10608 } 10609 10610 /*@C 10611 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10612 a given `Mat`. Each submatrix can span multiple procs. 10613 10614 Collective 10615 10616 Input Parameters: 10617 + mat - the matrix 10618 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10619 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10620 10621 Output Parameter: 10622 . subMat - parallel sub-matrices each spanning a given `subcomm` 10623 10624 Level: advanced 10625 10626 Notes: 10627 The submatrix partition across processors is dictated by `subComm` a 10628 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10629 is not restricted to be grouped with consecutive original MPI processes. 10630 10631 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10632 map directly to the layout of the original matrix [wrt the local 10633 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10634 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10635 the `subMat`. However the offDiagMat looses some columns - and this is 10636 reconstructed with `MatSetValues()` 10637 10638 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10639 10640 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10641 @*/ 10642 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10643 { 10644 PetscMPIInt commsize, subCommSize; 10645 10646 PetscFunctionBegin; 10647 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10648 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10649 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10650 10651 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"); 10652 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10653 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10654 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10655 PetscFunctionReturn(PETSC_SUCCESS); 10656 } 10657 10658 /*@ 10659 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10660 10661 Not Collective 10662 10663 Input Parameters: 10664 + mat - matrix to extract local submatrix from 10665 . isrow - local row indices for submatrix 10666 - iscol - local column indices for submatrix 10667 10668 Output Parameter: 10669 . submat - the submatrix 10670 10671 Level: intermediate 10672 10673 Notes: 10674 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10675 10676 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10677 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10678 10679 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10680 `MatSetValuesBlockedLocal()` will also be implemented. 10681 10682 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10683 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10684 10685 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10686 @*/ 10687 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10688 { 10689 PetscFunctionBegin; 10690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10691 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10692 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10693 PetscCheckSameComm(isrow, 2, iscol, 3); 10694 PetscAssertPointer(submat, 4); 10695 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10696 10697 if (mat->ops->getlocalsubmatrix) { 10698 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10699 } else { 10700 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10701 } 10702 PetscFunctionReturn(PETSC_SUCCESS); 10703 } 10704 10705 /*@ 10706 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10707 10708 Not Collective 10709 10710 Input Parameters: 10711 + mat - matrix to extract local submatrix from 10712 . isrow - local row indices for submatrix 10713 . iscol - local column indices for submatrix 10714 - submat - the submatrix 10715 10716 Level: intermediate 10717 10718 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10719 @*/ 10720 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10721 { 10722 PetscFunctionBegin; 10723 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10724 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10725 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10726 PetscCheckSameComm(isrow, 2, iscol, 3); 10727 PetscAssertPointer(submat, 4); 10728 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10729 10730 if (mat->ops->restorelocalsubmatrix) { 10731 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10732 } else { 10733 PetscCall(MatDestroy(submat)); 10734 } 10735 *submat = NULL; 10736 PetscFunctionReturn(PETSC_SUCCESS); 10737 } 10738 10739 /*@ 10740 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10741 10742 Collective 10743 10744 Input Parameter: 10745 . mat - the matrix 10746 10747 Output Parameter: 10748 . is - if any rows have zero diagonals this contains the list of them 10749 10750 Level: developer 10751 10752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10753 @*/ 10754 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10755 { 10756 PetscFunctionBegin; 10757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10758 PetscValidType(mat, 1); 10759 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10760 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10761 10762 if (!mat->ops->findzerodiagonals) { 10763 Vec diag; 10764 const PetscScalar *a; 10765 PetscInt *rows; 10766 PetscInt rStart, rEnd, r, nrow = 0; 10767 10768 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10769 PetscCall(MatGetDiagonal(mat, diag)); 10770 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10771 PetscCall(VecGetArrayRead(diag, &a)); 10772 for (r = 0; r < rEnd - rStart; ++r) 10773 if (a[r] == 0.0) ++nrow; 10774 PetscCall(PetscMalloc1(nrow, &rows)); 10775 nrow = 0; 10776 for (r = 0; r < rEnd - rStart; ++r) 10777 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10778 PetscCall(VecRestoreArrayRead(diag, &a)); 10779 PetscCall(VecDestroy(&diag)); 10780 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10781 } else { 10782 PetscUseTypeMethod(mat, findzerodiagonals, is); 10783 } 10784 PetscFunctionReturn(PETSC_SUCCESS); 10785 } 10786 10787 /*@ 10788 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10789 10790 Collective 10791 10792 Input Parameter: 10793 . mat - the matrix 10794 10795 Output Parameter: 10796 . is - contains the list of rows with off block diagonal entries 10797 10798 Level: developer 10799 10800 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10801 @*/ 10802 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10803 { 10804 PetscFunctionBegin; 10805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10806 PetscValidType(mat, 1); 10807 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10808 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10809 10810 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10811 PetscFunctionReturn(PETSC_SUCCESS); 10812 } 10813 10814 /*@C 10815 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10816 10817 Collective; No Fortran Support 10818 10819 Input Parameter: 10820 . mat - the matrix 10821 10822 Output Parameter: 10823 . values - the block inverses in column major order (FORTRAN-like) 10824 10825 Level: advanced 10826 10827 Notes: 10828 The size of the blocks is determined by the block size of the matrix. 10829 10830 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10831 10832 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10833 10834 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10835 @*/ 10836 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10837 { 10838 PetscFunctionBegin; 10839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10840 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10841 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10842 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10843 PetscFunctionReturn(PETSC_SUCCESS); 10844 } 10845 10846 /*@ 10847 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10848 10849 Collective; No Fortran Support 10850 10851 Input Parameters: 10852 + mat - the matrix 10853 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10854 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10855 10856 Output Parameter: 10857 . values - the block inverses in column major order (FORTRAN-like) 10858 10859 Level: advanced 10860 10861 Notes: 10862 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10863 10864 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10865 10866 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10867 @*/ 10868 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10869 { 10870 PetscFunctionBegin; 10871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10872 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10873 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10874 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10875 PetscFunctionReturn(PETSC_SUCCESS); 10876 } 10877 10878 /*@ 10879 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10880 10881 Collective 10882 10883 Input Parameters: 10884 + A - the matrix 10885 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10886 10887 Level: advanced 10888 10889 Note: 10890 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10891 10892 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10893 @*/ 10894 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10895 { 10896 const PetscScalar *vals; 10897 PetscInt *dnnz; 10898 PetscInt m, rstart, rend, bs, i, j; 10899 10900 PetscFunctionBegin; 10901 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10902 PetscCall(MatGetBlockSize(A, &bs)); 10903 PetscCall(MatGetLocalSize(A, &m, NULL)); 10904 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10905 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10906 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10907 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10908 PetscCall(PetscFree(dnnz)); 10909 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10910 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10911 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10912 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10913 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10914 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10915 PetscFunctionReturn(PETSC_SUCCESS); 10916 } 10917 10918 /*@ 10919 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10920 via `MatTransposeColoringCreate()`. 10921 10922 Collective 10923 10924 Input Parameter: 10925 . c - coloring context 10926 10927 Level: intermediate 10928 10929 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10930 @*/ 10931 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10932 { 10933 MatTransposeColoring matcolor = *c; 10934 10935 PetscFunctionBegin; 10936 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10937 if (--((PetscObject)matcolor)->refct > 0) { 10938 matcolor = NULL; 10939 PetscFunctionReturn(PETSC_SUCCESS); 10940 } 10941 10942 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10943 PetscCall(PetscFree(matcolor->rows)); 10944 PetscCall(PetscFree(matcolor->den2sp)); 10945 PetscCall(PetscFree(matcolor->colorforcol)); 10946 PetscCall(PetscFree(matcolor->columns)); 10947 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10948 PetscCall(PetscHeaderDestroy(c)); 10949 PetscFunctionReturn(PETSC_SUCCESS); 10950 } 10951 10952 /*@ 10953 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10954 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10955 `MatTransposeColoring` to sparse `B`. 10956 10957 Collective 10958 10959 Input Parameters: 10960 + coloring - coloring context created with `MatTransposeColoringCreate()` 10961 - B - sparse matrix 10962 10963 Output Parameter: 10964 . Btdense - dense matrix $B^T$ 10965 10966 Level: developer 10967 10968 Note: 10969 These are used internally for some implementations of `MatRARt()` 10970 10971 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10972 @*/ 10973 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10974 { 10975 PetscFunctionBegin; 10976 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10977 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10978 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10979 10980 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10981 PetscFunctionReturn(PETSC_SUCCESS); 10982 } 10983 10984 /*@ 10985 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10986 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10987 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10988 $C_{sp}$ from $C_{den}$. 10989 10990 Collective 10991 10992 Input Parameters: 10993 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10994 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10995 10996 Output Parameter: 10997 . Csp - sparse matrix 10998 10999 Level: developer 11000 11001 Note: 11002 These are used internally for some implementations of `MatRARt()` 11003 11004 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11005 @*/ 11006 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11007 { 11008 PetscFunctionBegin; 11009 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11010 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11011 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11012 11013 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11014 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11015 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11016 PetscFunctionReturn(PETSC_SUCCESS); 11017 } 11018 11019 /*@ 11020 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11021 11022 Collective 11023 11024 Input Parameters: 11025 + mat - the matrix product C 11026 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11027 11028 Output Parameter: 11029 . color - the new coloring context 11030 11031 Level: intermediate 11032 11033 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11034 `MatTransColoringApplyDenToSp()` 11035 @*/ 11036 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11037 { 11038 MatTransposeColoring c; 11039 MPI_Comm comm; 11040 11041 PetscFunctionBegin; 11042 PetscAssertPointer(color, 3); 11043 11044 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11045 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11046 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11047 c->ctype = iscoloring->ctype; 11048 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11049 *color = c; 11050 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11051 PetscFunctionReturn(PETSC_SUCCESS); 11052 } 11053 11054 /*@ 11055 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11056 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11057 11058 Not Collective 11059 11060 Input Parameter: 11061 . mat - the matrix 11062 11063 Output Parameter: 11064 . state - the current state 11065 11066 Level: intermediate 11067 11068 Notes: 11069 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11070 different matrices 11071 11072 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11073 11074 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11075 11076 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11077 @*/ 11078 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11079 { 11080 PetscFunctionBegin; 11081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11082 *state = mat->nonzerostate; 11083 PetscFunctionReturn(PETSC_SUCCESS); 11084 } 11085 11086 /*@ 11087 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11088 matrices from each processor 11089 11090 Collective 11091 11092 Input Parameters: 11093 + comm - the communicators the parallel matrix will live on 11094 . seqmat - the input sequential matrices 11095 . n - number of local columns (or `PETSC_DECIDE`) 11096 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11097 11098 Output Parameter: 11099 . mpimat - the parallel matrix generated 11100 11101 Level: developer 11102 11103 Note: 11104 The number of columns of the matrix in EACH processor MUST be the same. 11105 11106 .seealso: [](ch_matrices), `Mat` 11107 @*/ 11108 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11109 { 11110 PetscMPIInt size; 11111 11112 PetscFunctionBegin; 11113 PetscCallMPI(MPI_Comm_size(comm, &size)); 11114 if (size == 1) { 11115 if (reuse == MAT_INITIAL_MATRIX) { 11116 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11117 } else { 11118 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11119 } 11120 PetscFunctionReturn(PETSC_SUCCESS); 11121 } 11122 11123 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"); 11124 11125 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11126 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11127 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11128 PetscFunctionReturn(PETSC_SUCCESS); 11129 } 11130 11131 /*@ 11132 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11133 11134 Collective 11135 11136 Input Parameters: 11137 + A - the matrix to create subdomains from 11138 - N - requested number of subdomains 11139 11140 Output Parameters: 11141 + n - number of subdomains resulting on this MPI process 11142 - iss - `IS` list with indices of subdomains on this MPI process 11143 11144 Level: advanced 11145 11146 Note: 11147 The number of subdomains must be smaller than the communicator size 11148 11149 .seealso: [](ch_matrices), `Mat`, `IS` 11150 @*/ 11151 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11152 { 11153 MPI_Comm comm, subcomm; 11154 PetscMPIInt size, rank, color; 11155 PetscInt rstart, rend, k; 11156 11157 PetscFunctionBegin; 11158 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11159 PetscCallMPI(MPI_Comm_size(comm, &size)); 11160 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11161 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); 11162 *n = 1; 11163 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 11164 color = rank / k; 11165 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11166 PetscCall(PetscMalloc1(1, iss)); 11167 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11168 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11169 PetscCallMPI(MPI_Comm_free(&subcomm)); 11170 PetscFunctionReturn(PETSC_SUCCESS); 11171 } 11172 11173 /*@ 11174 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11175 11176 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11177 If they are not the same, uses `MatMatMatMult()`. 11178 11179 Once the coarse grid problem is constructed, correct for interpolation operators 11180 that are not of full rank, which can legitimately happen in the case of non-nested 11181 geometric multigrid. 11182 11183 Input Parameters: 11184 + restrct - restriction operator 11185 . dA - fine grid matrix 11186 . interpolate - interpolation operator 11187 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11188 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11189 11190 Output Parameter: 11191 . A - the Galerkin coarse matrix 11192 11193 Options Database Key: 11194 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11195 11196 Level: developer 11197 11198 Note: 11199 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11200 11201 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11202 @*/ 11203 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11204 { 11205 IS zerorows; 11206 Vec diag; 11207 11208 PetscFunctionBegin; 11209 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11210 /* Construct the coarse grid matrix */ 11211 if (interpolate == restrct) { 11212 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11213 } else { 11214 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11215 } 11216 11217 /* If the interpolation matrix is not of full rank, A will have zero rows. 11218 This can legitimately happen in the case of non-nested geometric multigrid. 11219 In that event, we set the rows of the matrix to the rows of the identity, 11220 ignoring the equations (as the RHS will also be zero). */ 11221 11222 PetscCall(MatFindZeroRows(*A, &zerorows)); 11223 11224 if (zerorows != NULL) { /* if there are any zero rows */ 11225 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11226 PetscCall(MatGetDiagonal(*A, diag)); 11227 PetscCall(VecISSet(diag, zerorows, 1.0)); 11228 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11229 PetscCall(VecDestroy(&diag)); 11230 PetscCall(ISDestroy(&zerorows)); 11231 } 11232 PetscFunctionReturn(PETSC_SUCCESS); 11233 } 11234 11235 /*@C 11236 MatSetOperation - Allows user to set a matrix operation for any matrix type 11237 11238 Logically Collective 11239 11240 Input Parameters: 11241 + mat - the matrix 11242 . op - the name of the operation 11243 - f - the function that provides the operation 11244 11245 Level: developer 11246 11247 Example Usage: 11248 .vb 11249 extern PetscErrorCode usermult(Mat, Vec, Vec); 11250 11251 PetscCall(MatCreateXXX(comm, ..., &A)); 11252 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11253 .ve 11254 11255 Notes: 11256 See the file `include/petscmat.h` for a complete list of matrix 11257 operations, which all have the form MATOP_<OPERATION>, where 11258 <OPERATION> is the name (in all capital letters) of the 11259 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11260 11261 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11262 sequence as the usual matrix interface routines, since they 11263 are intended to be accessed via the usual matrix interface 11264 routines, e.g., 11265 .vb 11266 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11267 .ve 11268 11269 In particular each function MUST return `PETSC_SUCCESS` on success and 11270 nonzero on failure. 11271 11272 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11273 11274 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11275 @*/ 11276 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11277 { 11278 PetscFunctionBegin; 11279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11280 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11281 (((void (**)(void))mat->ops)[op]) = f; 11282 PetscFunctionReturn(PETSC_SUCCESS); 11283 } 11284 11285 /*@C 11286 MatGetOperation - Gets a matrix operation for any matrix type. 11287 11288 Not Collective 11289 11290 Input Parameters: 11291 + mat - the matrix 11292 - op - the name of the operation 11293 11294 Output Parameter: 11295 . f - the function that provides the operation 11296 11297 Level: developer 11298 11299 Example Usage: 11300 .vb 11301 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11302 11303 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11304 .ve 11305 11306 Notes: 11307 See the file include/petscmat.h for a complete list of matrix 11308 operations, which all have the form MATOP_<OPERATION>, where 11309 <OPERATION> is the name (in all capital letters) of the 11310 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11311 11312 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11313 11314 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11315 @*/ 11316 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11317 { 11318 PetscFunctionBegin; 11319 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11320 *f = (((void (**)(void))mat->ops)[op]); 11321 PetscFunctionReturn(PETSC_SUCCESS); 11322 } 11323 11324 /*@ 11325 MatHasOperation - Determines whether the given matrix supports the particular operation. 11326 11327 Not Collective 11328 11329 Input Parameters: 11330 + mat - the matrix 11331 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11332 11333 Output Parameter: 11334 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11335 11336 Level: advanced 11337 11338 Note: 11339 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11340 11341 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11342 @*/ 11343 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11344 { 11345 PetscFunctionBegin; 11346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11347 PetscAssertPointer(has, 3); 11348 if (mat->ops->hasoperation) { 11349 PetscUseTypeMethod(mat, hasoperation, op, has); 11350 } else { 11351 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11352 else { 11353 *has = PETSC_FALSE; 11354 if (op == MATOP_CREATE_SUBMATRIX) { 11355 PetscMPIInt size; 11356 11357 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11358 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11359 } 11360 } 11361 } 11362 PetscFunctionReturn(PETSC_SUCCESS); 11363 } 11364 11365 /*@ 11366 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11367 11368 Collective 11369 11370 Input Parameter: 11371 . mat - the matrix 11372 11373 Output Parameter: 11374 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11375 11376 Level: beginner 11377 11378 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11379 @*/ 11380 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11381 { 11382 PetscFunctionBegin; 11383 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11384 PetscValidType(mat, 1); 11385 PetscAssertPointer(cong, 2); 11386 if (!mat->rmap || !mat->cmap) { 11387 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11388 PetscFunctionReturn(PETSC_SUCCESS); 11389 } 11390 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11391 PetscCall(PetscLayoutSetUp(mat->rmap)); 11392 PetscCall(PetscLayoutSetUp(mat->cmap)); 11393 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11394 if (*cong) mat->congruentlayouts = 1; 11395 else mat->congruentlayouts = 0; 11396 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11397 PetscFunctionReturn(PETSC_SUCCESS); 11398 } 11399 11400 PetscErrorCode MatSetInf(Mat A) 11401 { 11402 PetscFunctionBegin; 11403 PetscUseTypeMethod(A, setinf); 11404 PetscFunctionReturn(PETSC_SUCCESS); 11405 } 11406 11407 /*@ 11408 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 11409 and possibly removes small values from the graph structure. 11410 11411 Collective 11412 11413 Input Parameters: 11414 + A - the matrix 11415 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11416 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11417 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11418 . num_idx - size of 'index' array 11419 - index - array of block indices to use for graph strength of connection weight 11420 11421 Output Parameter: 11422 . graph - the resulting graph 11423 11424 Level: advanced 11425 11426 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11427 @*/ 11428 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11429 { 11430 PetscFunctionBegin; 11431 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11432 PetscValidType(A, 1); 11433 PetscValidLogicalCollectiveBool(A, scale, 3); 11434 PetscAssertPointer(graph, 7); 11435 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11436 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11437 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11438 PetscFunctionReturn(PETSC_SUCCESS); 11439 } 11440 11441 /*@ 11442 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11443 meaning the same memory is used for the matrix, and no new memory is allocated. 11444 11445 Collective 11446 11447 Input Parameters: 11448 + A - the matrix 11449 - 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 11450 11451 Level: intermediate 11452 11453 Developer Note: 11454 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11455 of the arrays in the data structure are unneeded. 11456 11457 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11458 @*/ 11459 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11460 { 11461 PetscFunctionBegin; 11462 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11463 PetscUseTypeMethod(A, eliminatezeros, keep); 11464 PetscFunctionReturn(PETSC_SUCCESS); 11465 } 11466