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 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 The calling sequence is 586 .vb 587 MatGetRow(matrix,row,ncols,cols,values,ierr) 588 Mat matrix (input) 589 PetscInt row (input) 590 PetscInt ncols (output) 591 PetscInt cols(maxcols) (output) 592 PetscScalar values(maxcols) output 593 .ve 594 where maxcols >= maximum nonzeros in any row of the matrix. 595 596 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 597 @*/ 598 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 599 { 600 PetscInt incols; 601 602 PetscFunctionBegin; 603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 604 PetscValidType(mat, 1); 605 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 607 MatCheckPreallocated(mat, 1); 608 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); 609 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 610 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 611 if (ncols) *ncols = incols; 612 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 613 PetscFunctionReturn(PETSC_SUCCESS); 614 } 615 616 /*@ 617 MatConjugate - replaces the matrix values with their complex conjugates 618 619 Logically Collective 620 621 Input Parameter: 622 . mat - the matrix 623 624 Level: advanced 625 626 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 627 @*/ 628 PetscErrorCode MatConjugate(Mat mat) 629 { 630 PetscFunctionBegin; 631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 632 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 633 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 634 PetscUseTypeMethod(mat, conjugate); 635 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 636 } 637 PetscFunctionReturn(PETSC_SUCCESS); 638 } 639 640 /*@C 641 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 642 643 Not Collective 644 645 Input Parameters: 646 + mat - the matrix 647 . row - the row to get 648 . ncols - the number of nonzeros 649 . cols - the columns of the nonzeros 650 - vals - if nonzero the column values 651 652 Level: advanced 653 654 Notes: 655 This routine should be called after you have finished examining the entries. 656 657 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 658 us of the array after it has been restored. If you pass `NULL`, it will 659 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 660 661 Fortran Note: 662 `MatRestoreRow()` MUST be called after `MatGetRow()` 663 before another call to `MatGetRow()` can be made. 664 665 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 666 @*/ 667 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 668 { 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 671 if (ncols) PetscAssertPointer(ncols, 3); 672 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 673 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 674 if (ncols) *ncols = 0; 675 if (cols) *cols = NULL; 676 if (vals) *vals = NULL; 677 PetscFunctionReturn(PETSC_SUCCESS); 678 } 679 680 /*@ 681 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 682 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 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. 693 694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 PetscTryTypeMethod(mat, getrowuppertriangular); 705 PetscFunctionReturn(PETSC_SUCCESS); 706 } 707 708 /*@ 709 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 710 711 Not Collective 712 713 Input Parameter: 714 . mat - the matrix 715 716 Level: advanced 717 718 Note: 719 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 720 721 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 722 @*/ 723 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 724 { 725 PetscFunctionBegin; 726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 727 PetscValidType(mat, 1); 728 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 729 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 730 MatCheckPreallocated(mat, 1); 731 PetscTryTypeMethod(mat, restorerowuppertriangular); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@ 736 MatSetOptionsPrefix - Sets the prefix used for searching for all 737 `Mat` options in the database. 738 739 Logically Collective 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names 744 745 Level: advanced 746 747 Notes: 748 A hyphen (-) must NOT be given at the beginning of the prefix name. 749 The first character of all runtime options is AUTOMATICALLY the hyphen. 750 751 This is NOT used for options for the factorization of the matrix. Normally the 752 prefix is automatically passed in from the PC calling the factorization. To set 753 it directly use `MatSetOptionsPrefixFactor()` 754 755 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 756 @*/ 757 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 758 { 759 PetscFunctionBegin; 760 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 761 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 762 PetscFunctionReturn(PETSC_SUCCESS); 763 } 764 765 /*@ 766 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 767 for matrices created with `MatGetFactor()` 768 769 Logically Collective 770 771 Input Parameters: 772 + A - the matrix 773 - prefix - the prefix to prepend to all option names for the factored matrix 774 775 Level: developer 776 777 Notes: 778 A hyphen (-) must NOT be given at the beginning of the prefix name. 779 The first character of all runtime options is AUTOMATICALLY the hyphen. 780 781 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 782 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 783 784 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 785 @*/ 786 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 787 { 788 PetscFunctionBegin; 789 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 790 if (prefix) { 791 PetscAssertPointer(prefix, 2); 792 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 793 if (prefix != A->factorprefix) { 794 PetscCall(PetscFree(A->factorprefix)); 795 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 796 } 797 } else PetscCall(PetscFree(A->factorprefix)); 798 PetscFunctionReturn(PETSC_SUCCESS); 799 } 800 801 /*@ 802 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 803 for matrices created with `MatGetFactor()` 804 805 Logically Collective 806 807 Input Parameters: 808 + A - the matrix 809 - prefix - the prefix to prepend to all option names for the factored matrix 810 811 Level: developer 812 813 Notes: 814 A hyphen (-) must NOT be given at the beginning of the prefix name. 815 The first character of all runtime options is AUTOMATICALLY the hyphen. 816 817 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 818 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 819 820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 821 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 822 `MatSetOptionsPrefix()` 823 @*/ 824 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 825 { 826 size_t len1, len2, new_len; 827 828 PetscFunctionBegin; 829 PetscValidHeader(A, 1); 830 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 831 if (!A->factorprefix) { 832 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 833 PetscFunctionReturn(PETSC_SUCCESS); 834 } 835 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 836 837 PetscCall(PetscStrlen(A->factorprefix, &len1)); 838 PetscCall(PetscStrlen(prefix, &len2)); 839 new_len = len1 + len2 + 1; 840 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 841 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@ 846 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 847 matrix options in the database. 848 849 Logically Collective 850 851 Input Parameters: 852 + A - the matrix 853 - prefix - the prefix to prepend to all option names 854 855 Level: advanced 856 857 Note: 858 A hyphen (-) must NOT be given at the beginning of the prefix name. 859 The first character of all runtime options is AUTOMATICALLY the hyphen. 860 861 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 862 @*/ 863 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 867 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 868 PetscFunctionReturn(PETSC_SUCCESS); 869 } 870 871 /*@ 872 MatGetOptionsPrefix - Gets the prefix used for searching for all 873 matrix options in the database. 874 875 Not Collective 876 877 Input Parameter: 878 . A - the matrix 879 880 Output Parameter: 881 . prefix - pointer to the prefix string used 882 883 Level: advanced 884 885 Fortran Note: 886 The user should pass in a string `prefix` of 887 sufficient length to hold the prefix. 888 889 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 890 @*/ 891 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 892 { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 895 PetscAssertPointer(prefix, 2); 896 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 897 PetscFunctionReturn(PETSC_SUCCESS); 898 } 899 900 /*@ 901 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 902 903 Not Collective 904 905 Input Parameter: 906 . A - the matrix 907 908 Output Parameter: 909 . state - the object state 910 911 Level: advanced 912 913 Note: 914 Object state is an integer which gets increased every time 915 the object is changed. By saving and later querying the object state 916 one can determine whether information about the object is still current. 917 918 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 919 920 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 921 @*/ 922 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 PetscAssertPointer(state, 2); 927 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 928 PetscFunctionReturn(PETSC_SUCCESS); 929 } 930 931 /*@ 932 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 933 934 Collective 935 936 Input Parameter: 937 . A - the matrix 938 939 Level: beginner 940 941 Notes: 942 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 943 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 944 makes all of the preallocation space available 945 946 Current values in the matrix are lost in this call. 947 948 Currently only supported for `MATAIJ` matrices. 949 950 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 951 @*/ 952 PetscErrorCode MatResetPreallocation(Mat A) 953 { 954 PetscFunctionBegin; 955 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 956 PetscValidType(A, 1); 957 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()"); 958 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 959 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 960 PetscFunctionReturn(PETSC_SUCCESS); 961 } 962 963 /*@ 964 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 965 966 Collective 967 968 Input Parameter: 969 . A - the matrix 970 971 Level: intermediate 972 973 Notes: 974 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 975 976 Currently only supported for `MATAIJ` matrices. 977 978 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 979 @*/ 980 PetscErrorCode MatResetHash(Mat A) 981 { 982 PetscFunctionBegin; 983 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 984 PetscValidType(A, 1); 985 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 986 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 987 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 988 /* These flags are used to determine whether certain setups occur */ 989 A->was_assembled = PETSC_FALSE; 990 A->assembled = PETSC_FALSE; 991 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 992 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 993 PetscFunctionReturn(PETSC_SUCCESS); 994 } 995 996 /*@ 997 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 998 999 Collective 1000 1001 Input Parameter: 1002 . A - the matrix 1003 1004 Level: advanced 1005 1006 Notes: 1007 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1008 setting values in the matrix. 1009 1010 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1011 1012 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1013 @*/ 1014 PetscErrorCode MatSetUp(Mat A) 1015 { 1016 PetscFunctionBegin; 1017 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1018 if (!((PetscObject)A)->type_name) { 1019 PetscMPIInt size; 1020 1021 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1022 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1023 } 1024 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1025 PetscCall(PetscLayoutSetUp(A->rmap)); 1026 PetscCall(PetscLayoutSetUp(A->cmap)); 1027 A->preallocated = PETSC_TRUE; 1028 PetscFunctionReturn(PETSC_SUCCESS); 1029 } 1030 1031 #if defined(PETSC_HAVE_SAWS) 1032 #include <petscviewersaws.h> 1033 #endif 1034 1035 /* 1036 If threadsafety is on extraneous matrices may be printed 1037 1038 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1039 */ 1040 #if !defined(PETSC_HAVE_THREADSAFETY) 1041 static PetscInt insidematview = 0; 1042 #endif 1043 1044 /*@ 1045 MatViewFromOptions - View properties of the matrix based on options set in the options database 1046 1047 Collective 1048 1049 Input Parameters: 1050 + A - the matrix 1051 . obj - optional additional object that provides the options prefix to use 1052 - name - command line option 1053 1054 Options Database Key: 1055 . -mat_view [viewertype]:... - the viewer and its options 1056 1057 Level: intermediate 1058 1059 Note: 1060 .vb 1061 If no value is provided ascii:stdout is used 1062 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1063 for example ascii::ascii_info prints just the information about the object not all details 1064 unless :append is given filename opens in write mode, overwriting what was already there 1065 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1066 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1067 socket[:port] defaults to the standard output port 1068 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1069 .ve 1070 1071 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1072 @*/ 1073 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1074 { 1075 PetscFunctionBegin; 1076 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1077 #if !defined(PETSC_HAVE_THREADSAFETY) 1078 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1079 #endif 1080 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1081 PetscFunctionReturn(PETSC_SUCCESS); 1082 } 1083 1084 /*@ 1085 MatView - display information about a matrix in a variety ways 1086 1087 Collective on viewer 1088 1089 Input Parameters: 1090 + mat - the matrix 1091 - viewer - visualization context 1092 1093 Options Database Keys: 1094 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1095 . -mat_view ::ascii_info_detail - Prints more detailed info 1096 . -mat_view - Prints matrix in ASCII format 1097 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1098 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1099 . -display <name> - Sets display name (default is host) 1100 . -draw_pause <sec> - Sets number of seconds to pause after display 1101 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1102 . -viewer_socket_machine <machine> - - 1103 . -viewer_socket_port <port> - - 1104 . -mat_view binary - save matrix to file in binary format 1105 - -viewer_binary_filename <name> - - 1106 1107 Level: beginner 1108 1109 Notes: 1110 The available visualization contexts include 1111 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1112 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1113 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1114 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1115 1116 The user can open alternative visualization contexts with 1117 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1118 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1119 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1120 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1121 1122 The user can call `PetscViewerPushFormat()` to specify the output 1123 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1124 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1125 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1126 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1127 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1128 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1129 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1130 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1131 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1132 1133 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1134 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1135 1136 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1137 1138 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1139 viewer is used. 1140 1141 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1142 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1143 1144 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1145 and then use the following mouse functions. 1146 .vb 1147 left mouse: zoom in 1148 middle mouse: zoom out 1149 right mouse: continue with the simulation 1150 .ve 1151 1152 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1153 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1154 @*/ 1155 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1156 { 1157 PetscInt rows, cols, rbs, cbs; 1158 PetscBool isascii, isstring, issaws; 1159 PetscViewerFormat format; 1160 PetscMPIInt size; 1161 1162 PetscFunctionBegin; 1163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1164 PetscValidType(mat, 1); 1165 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1166 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1167 1168 PetscCall(PetscViewerGetFormat(viewer, &format)); 1169 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1170 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1171 1172 #if !defined(PETSC_HAVE_THREADSAFETY) 1173 insidematview++; 1174 #endif 1175 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1176 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1177 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1178 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"); 1179 1180 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1181 if (isascii) { 1182 if (!mat->preallocated) { 1183 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1184 #if !defined(PETSC_HAVE_THREADSAFETY) 1185 insidematview--; 1186 #endif 1187 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1188 PetscFunctionReturn(PETSC_SUCCESS); 1189 } 1190 if (!mat->assembled) { 1191 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1192 #if !defined(PETSC_HAVE_THREADSAFETY) 1193 insidematview--; 1194 #endif 1195 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1196 PetscFunctionReturn(PETSC_SUCCESS); 1197 } 1198 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1199 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1200 MatNullSpace nullsp, transnullsp; 1201 1202 PetscCall(PetscViewerASCIIPushTab(viewer)); 1203 PetscCall(MatGetSize(mat, &rows, &cols)); 1204 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1205 if (rbs != 1 || cbs != 1) { 1206 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" : "")); 1207 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1208 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1209 if (mat->factortype) { 1210 MatSolverType solver; 1211 PetscCall(MatFactorGetSolverType(mat, &solver)); 1212 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1213 } 1214 if (mat->ops->getinfo) { 1215 MatInfo info; 1216 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1217 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1218 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1219 } 1220 PetscCall(MatGetNullSpace(mat, &nullsp)); 1221 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1222 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1223 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1224 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1225 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1226 PetscCall(PetscViewerASCIIPushTab(viewer)); 1227 PetscCall(MatProductView(mat, viewer)); 1228 PetscCall(PetscViewerASCIIPopTab(viewer)); 1229 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1230 IS tmp; 1231 1232 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1233 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1234 PetscCall(PetscViewerASCIIPushTab(viewer)); 1235 PetscCall(ISView(tmp, viewer)); 1236 PetscCall(PetscViewerASCIIPopTab(viewer)); 1237 PetscCall(ISDestroy(&tmp)); 1238 } 1239 } 1240 } else if (issaws) { 1241 #if defined(PETSC_HAVE_SAWS) 1242 PetscMPIInt rank; 1243 1244 PetscCall(PetscObjectName((PetscObject)mat)); 1245 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1246 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1247 #endif 1248 } else if (isstring) { 1249 const char *type; 1250 PetscCall(MatGetType(mat, &type)); 1251 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1252 PetscTryTypeMethod(mat, view, viewer); 1253 } 1254 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1255 PetscCall(PetscViewerASCIIPushTab(viewer)); 1256 PetscUseTypeMethod(mat, viewnative, viewer); 1257 PetscCall(PetscViewerASCIIPopTab(viewer)); 1258 } else if (mat->ops->view) { 1259 PetscCall(PetscViewerASCIIPushTab(viewer)); 1260 PetscUseTypeMethod(mat, view, viewer); 1261 PetscCall(PetscViewerASCIIPopTab(viewer)); 1262 } 1263 if (isascii) { 1264 PetscCall(PetscViewerGetFormat(viewer, &format)); 1265 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1266 } 1267 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1268 #if !defined(PETSC_HAVE_THREADSAFETY) 1269 insidematview--; 1270 #endif 1271 PetscFunctionReturn(PETSC_SUCCESS); 1272 } 1273 1274 #if defined(PETSC_USE_DEBUG) 1275 #include <../src/sys/totalview/tv_data_display.h> 1276 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1277 { 1278 TV_add_row("Local rows", "int", &mat->rmap->n); 1279 TV_add_row("Local columns", "int", &mat->cmap->n); 1280 TV_add_row("Global rows", "int", &mat->rmap->N); 1281 TV_add_row("Global columns", "int", &mat->cmap->N); 1282 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1283 return TV_format_OK; 1284 } 1285 #endif 1286 1287 /*@ 1288 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1289 with `MatView()`. The matrix format is determined from the options database. 1290 Generates a parallel MPI matrix if the communicator has more than one 1291 processor. The default matrix type is `MATAIJ`. 1292 1293 Collective 1294 1295 Input Parameters: 1296 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1297 or some related function before a call to `MatLoad()` 1298 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1299 1300 Options Database Key: 1301 . -matload_block_size <bs> - set block size 1302 1303 Level: beginner 1304 1305 Notes: 1306 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1307 `Mat` before calling this routine if you wish to set it from the options database. 1308 1309 `MatLoad()` automatically loads into the options database any options 1310 given in the file filename.info where filename is the name of the file 1311 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1312 file will be ignored if you use the -viewer_binary_skip_info option. 1313 1314 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1315 sets the default matrix type AIJ and sets the local and global sizes. 1316 If type and/or size is already set, then the same are used. 1317 1318 In parallel, each processor can load a subset of rows (or the 1319 entire matrix). This routine is especially useful when a large 1320 matrix is stored on disk and only part of it is desired on each 1321 processor. For example, a parallel solver may access only some of 1322 the rows from each processor. The algorithm used here reads 1323 relatively small blocks of data rather than reading the entire 1324 matrix and then subsetting it. 1325 1326 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1327 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1328 or the sequence like 1329 .vb 1330 `PetscViewer` v; 1331 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1332 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1333 `PetscViewerSetFromOptions`(v); 1334 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1335 `PetscViewerFileSetName`(v,"datafile"); 1336 .ve 1337 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1338 $ -viewer_type {binary, hdf5} 1339 1340 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1341 and src/mat/tutorials/ex10.c with the second approach. 1342 1343 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1344 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1345 Multiple objects, both matrices and vectors, can be stored within the same file. 1346 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1347 1348 Most users should not need to know the details of the binary storage 1349 format, since `MatLoad()` and `MatView()` completely hide these details. 1350 But for anyone who is interested, the standard binary matrix storage 1351 format is 1352 1353 .vb 1354 PetscInt MAT_FILE_CLASSID 1355 PetscInt number of rows 1356 PetscInt number of columns 1357 PetscInt total number of nonzeros 1358 PetscInt *number nonzeros in each row 1359 PetscInt *column indices of all nonzeros (starting index is zero) 1360 PetscScalar *values of all nonzeros 1361 .ve 1362 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1363 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 1364 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1365 1366 PETSc automatically does the byte swapping for 1367 machines that store the bytes reversed. Thus if you write your own binary 1368 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1369 and `PetscBinaryWrite()` to see how this may be done. 1370 1371 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1372 Each processor's chunk is loaded independently by its owning MPI process. 1373 Multiple objects, both matrices and vectors, can be stored within the same file. 1374 They are looked up by their PetscObject name. 1375 1376 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1377 by default the same structure and naming of the AIJ arrays and column count 1378 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1379 $ save example.mat A b -v7.3 1380 can be directly read by this routine (see Reference 1 for details). 1381 1382 Depending on your MATLAB version, this format might be a default, 1383 otherwise you can set it as default in Preferences. 1384 1385 Unless -nocompression flag is used to save the file in MATLAB, 1386 PETSc must be configured with ZLIB package. 1387 1388 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1389 1390 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1391 1392 Corresponding `MatView()` is not yet implemented. 1393 1394 The loaded matrix is actually a transpose of the original one in MATLAB, 1395 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1396 With this format, matrix is automatically transposed by PETSc, 1397 unless the matrix is marked as SPD or symmetric 1398 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1399 1400 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1401 1402 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1403 @*/ 1404 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1405 { 1406 PetscBool flg; 1407 1408 PetscFunctionBegin; 1409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1410 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1411 1412 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1413 1414 flg = PETSC_FALSE; 1415 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1416 if (flg) { 1417 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1418 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1419 } 1420 flg = PETSC_FALSE; 1421 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1422 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1423 1424 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1425 PetscUseTypeMethod(mat, load, viewer); 1426 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1427 PetscFunctionReturn(PETSC_SUCCESS); 1428 } 1429 1430 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1431 { 1432 Mat_Redundant *redund = *redundant; 1433 1434 PetscFunctionBegin; 1435 if (redund) { 1436 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1437 PetscCall(ISDestroy(&redund->isrow)); 1438 PetscCall(ISDestroy(&redund->iscol)); 1439 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1440 } else { 1441 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1442 PetscCall(PetscFree(redund->sbuf_j)); 1443 PetscCall(PetscFree(redund->sbuf_a)); 1444 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1445 PetscCall(PetscFree(redund->rbuf_j[i])); 1446 PetscCall(PetscFree(redund->rbuf_a[i])); 1447 } 1448 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1449 } 1450 1451 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1452 PetscCall(PetscFree(redund)); 1453 } 1454 PetscFunctionReturn(PETSC_SUCCESS); 1455 } 1456 1457 /*@ 1458 MatDestroy - Frees space taken by a matrix. 1459 1460 Collective 1461 1462 Input Parameter: 1463 . A - the matrix 1464 1465 Level: beginner 1466 1467 Developer Note: 1468 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1469 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1470 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1471 if changes are needed here. 1472 1473 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1474 @*/ 1475 PetscErrorCode MatDestroy(Mat *A) 1476 { 1477 PetscFunctionBegin; 1478 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1479 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1480 if (--((PetscObject)*A)->refct > 0) { 1481 *A = NULL; 1482 PetscFunctionReturn(PETSC_SUCCESS); 1483 } 1484 1485 /* if memory was published with SAWs then destroy it */ 1486 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1487 PetscTryTypeMethod(*A, destroy); 1488 1489 PetscCall(PetscFree((*A)->factorprefix)); 1490 PetscCall(PetscFree((*A)->defaultvectype)); 1491 PetscCall(PetscFree((*A)->defaultrandtype)); 1492 PetscCall(PetscFree((*A)->bsizes)); 1493 PetscCall(PetscFree((*A)->solvertype)); 1494 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1495 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1496 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1497 PetscCall(MatProductClear(*A)); 1498 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1499 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1500 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1501 PetscCall(MatDestroy(&(*A)->schur)); 1502 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1503 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1504 PetscCall(PetscHeaderDestroy(A)); 1505 PetscFunctionReturn(PETSC_SUCCESS); 1506 } 1507 1508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1509 /*@ 1510 MatSetValues - Inserts or adds a block of values into a matrix. 1511 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1512 MUST be called after all calls to `MatSetValues()` have been completed. 1513 1514 Not Collective 1515 1516 Input Parameters: 1517 + mat - the matrix 1518 . v - a logically two-dimensional array of values 1519 . m - the number of rows 1520 . idxm - the global indices of the rows 1521 . n - the number of columns 1522 . idxn - the global indices of the columns 1523 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1524 1525 Level: beginner 1526 1527 Notes: 1528 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1529 1530 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1531 options cannot be mixed without intervening calls to the assembly 1532 routines. 1533 1534 `MatSetValues()` uses 0-based row and column numbers in Fortran 1535 as well as in C. 1536 1537 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1538 simply ignored. This allows easily inserting element stiffness matrices 1539 with homogeneous Dirichlet boundary conditions that you don't want represented 1540 in the matrix. 1541 1542 Efficiency Alert: 1543 The routine `MatSetValuesBlocked()` may offer much better efficiency 1544 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1545 1546 Fortran Notes: 1547 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1548 .vb 1549 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1550 .ve 1551 1552 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1553 1554 Developer Note: 1555 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1556 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1557 1558 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1559 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1560 @*/ 1561 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1562 { 1563 PetscFunctionBeginHot; 1564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1565 PetscValidType(mat, 1); 1566 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1567 PetscAssertPointer(idxm, 3); 1568 PetscAssertPointer(idxn, 5); 1569 MatCheckPreallocated(mat, 1); 1570 1571 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1572 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1573 1574 if (PetscDefined(USE_DEBUG)) { 1575 PetscInt i, j; 1576 1577 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1578 if (v) { 1579 for (i = 0; i < m; i++) { 1580 for (j = 0; j < n; j++) { 1581 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1582 #if defined(PETSC_USE_COMPLEX) 1583 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]); 1584 #else 1585 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]); 1586 #endif 1587 } 1588 } 1589 } 1590 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); 1591 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); 1592 } 1593 1594 if (mat->assembled) { 1595 mat->was_assembled = PETSC_TRUE; 1596 mat->assembled = PETSC_FALSE; 1597 } 1598 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1599 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1600 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1605 /*@ 1606 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1607 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1608 MUST be called after all calls to `MatSetValues()` have been completed. 1609 1610 Not Collective 1611 1612 Input Parameters: 1613 + mat - the matrix 1614 . v - a logically two-dimensional array of values 1615 . ism - the rows to provide 1616 . isn - the columns to provide 1617 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1618 1619 Level: beginner 1620 1621 Notes: 1622 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1623 1624 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1625 options cannot be mixed without intervening calls to the assembly 1626 routines. 1627 1628 `MatSetValues()` uses 0-based row and column numbers in Fortran 1629 as well as in C. 1630 1631 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1632 simply ignored. This allows easily inserting element stiffness matrices 1633 with homogeneous Dirichlet boundary conditions that you don't want represented 1634 in the matrix. 1635 1636 Efficiency Alert: 1637 The routine `MatSetValuesBlocked()` may offer much better efficiency 1638 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1639 1640 This is currently not optimized for any particular `ISType` 1641 1642 Developer Note: 1643 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1644 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1645 1646 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1647 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1648 @*/ 1649 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1650 { 1651 PetscInt m, n; 1652 const PetscInt *rows, *cols; 1653 1654 PetscFunctionBeginHot; 1655 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1656 PetscCall(ISGetIndices(ism, &rows)); 1657 PetscCall(ISGetIndices(isn, &cols)); 1658 PetscCall(ISGetLocalSize(ism, &m)); 1659 PetscCall(ISGetLocalSize(isn, &n)); 1660 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1661 PetscCall(ISRestoreIndices(ism, &rows)); 1662 PetscCall(ISRestoreIndices(isn, &cols)); 1663 PetscFunctionReturn(PETSC_SUCCESS); 1664 } 1665 1666 /*@ 1667 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1668 values into a matrix 1669 1670 Not Collective 1671 1672 Input Parameters: 1673 + mat - the matrix 1674 . row - the (block) row to set 1675 - v - a logically two-dimensional array of values 1676 1677 Level: intermediate 1678 1679 Notes: 1680 The values, `v`, are column-oriented (for the block version) and sorted 1681 1682 All the nonzero values in `row` must be provided 1683 1684 The matrix must have previously had its column indices set, likely by having been assembled. 1685 1686 `row` must belong to this MPI process 1687 1688 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1689 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1690 @*/ 1691 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1692 { 1693 PetscInt globalrow; 1694 1695 PetscFunctionBegin; 1696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1697 PetscValidType(mat, 1); 1698 PetscAssertPointer(v, 3); 1699 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1700 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1701 PetscFunctionReturn(PETSC_SUCCESS); 1702 } 1703 1704 /*@ 1705 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1706 values into a matrix 1707 1708 Not Collective 1709 1710 Input Parameters: 1711 + mat - the matrix 1712 . row - the (block) row to set 1713 - 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 1714 1715 Level: advanced 1716 1717 Notes: 1718 The values, `v`, are column-oriented for the block version. 1719 1720 All the nonzeros in `row` must be provided 1721 1722 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1723 1724 `row` must belong to this process 1725 1726 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1727 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1728 @*/ 1729 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1730 { 1731 PetscFunctionBeginHot; 1732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1733 PetscValidType(mat, 1); 1734 MatCheckPreallocated(mat, 1); 1735 PetscAssertPointer(v, 3); 1736 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1737 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1738 mat->insertmode = INSERT_VALUES; 1739 1740 if (mat->assembled) { 1741 mat->was_assembled = PETSC_TRUE; 1742 mat->assembled = PETSC_FALSE; 1743 } 1744 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1745 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1746 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1747 PetscFunctionReturn(PETSC_SUCCESS); 1748 } 1749 1750 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1751 /*@ 1752 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1753 Using structured grid indexing 1754 1755 Not Collective 1756 1757 Input Parameters: 1758 + mat - the matrix 1759 . m - number of rows being entered 1760 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1761 . n - number of columns being entered 1762 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1763 . v - a logically two-dimensional array of values 1764 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1765 1766 Level: beginner 1767 1768 Notes: 1769 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1770 1771 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1772 options cannot be mixed without intervening calls to the assembly 1773 routines. 1774 1775 The grid coordinates are across the entire grid, not just the local portion 1776 1777 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1778 as well as in C. 1779 1780 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1781 1782 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1783 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1784 1785 The columns and rows in the stencil passed in MUST be contained within the 1786 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1787 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1788 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1789 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1790 1791 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1792 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1793 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1794 `DM_BOUNDARY_PERIODIC` boundary type. 1795 1796 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 1797 a single value per point) you can skip filling those indices. 1798 1799 Inspired by the structured grid interface to the HYPRE package 1800 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1801 1802 Efficiency Alert: 1803 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1804 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1805 1806 Fortran Note: 1807 `idxm` and `idxn` should be declared as 1808 $ MatStencil idxm(4,m),idxn(4,n) 1809 and the values inserted using 1810 .vb 1811 idxm(MatStencil_i,1) = i 1812 idxm(MatStencil_j,1) = j 1813 idxm(MatStencil_k,1) = k 1814 idxm(MatStencil_c,1) = c 1815 etc 1816 .ve 1817 1818 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1819 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1820 @*/ 1821 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1822 { 1823 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1824 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1825 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1826 1827 PetscFunctionBegin; 1828 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1829 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1830 PetscValidType(mat, 1); 1831 PetscAssertPointer(idxm, 3); 1832 PetscAssertPointer(idxn, 5); 1833 1834 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1835 jdxm = buf; 1836 jdxn = buf + m; 1837 } else { 1838 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1839 jdxm = bufm; 1840 jdxn = bufn; 1841 } 1842 for (i = 0; i < m; i++) { 1843 for (j = 0; j < 3 - sdim; j++) dxm++; 1844 tmp = *dxm++ - starts[0]; 1845 for (j = 0; j < dim - 1; j++) { 1846 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1847 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1848 } 1849 if (mat->stencil.noc) dxm++; 1850 jdxm[i] = tmp; 1851 } 1852 for (i = 0; i < n; i++) { 1853 for (j = 0; j < 3 - sdim; j++) dxn++; 1854 tmp = *dxn++ - starts[0]; 1855 for (j = 0; j < dim - 1; j++) { 1856 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1857 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1858 } 1859 if (mat->stencil.noc) dxn++; 1860 jdxn[i] = tmp; 1861 } 1862 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1863 PetscCall(PetscFree2(bufm, bufn)); 1864 PetscFunctionReturn(PETSC_SUCCESS); 1865 } 1866 1867 /*@ 1868 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1869 Using structured grid indexing 1870 1871 Not Collective 1872 1873 Input Parameters: 1874 + mat - the matrix 1875 . m - number of rows being entered 1876 . idxm - grid coordinates for matrix rows being entered 1877 . n - number of columns being entered 1878 . idxn - grid coordinates for matrix columns being entered 1879 . v - a logically two-dimensional array of values 1880 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1881 1882 Level: beginner 1883 1884 Notes: 1885 By default the values, `v`, are row-oriented and unsorted. 1886 See `MatSetOption()` for other options. 1887 1888 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1889 options cannot be mixed without intervening calls to the assembly 1890 routines. 1891 1892 The grid coordinates are across the entire grid, not just the local portion 1893 1894 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1895 as well as in C. 1896 1897 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1898 1899 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1900 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1901 1902 The columns and rows in the stencil passed in MUST be contained within the 1903 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1904 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1905 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1906 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1907 1908 Negative indices may be passed in idxm and idxn, these rows and columns are 1909 simply ignored. This allows easily inserting element stiffness matrices 1910 with homogeneous Dirichlet boundary conditions that you don't want represented 1911 in the matrix. 1912 1913 Inspired by the structured grid interface to the HYPRE package 1914 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1915 1916 Fortran Note: 1917 `idxm` and `idxn` should be declared as 1918 $ MatStencil idxm(4,m),idxn(4,n) 1919 and the values inserted using 1920 .vb 1921 idxm(MatStencil_i,1) = i 1922 idxm(MatStencil_j,1) = j 1923 idxm(MatStencil_k,1) = k 1924 etc 1925 .ve 1926 1927 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1928 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1929 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1930 @*/ 1931 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1932 { 1933 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1934 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1935 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1936 1937 PetscFunctionBegin; 1938 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1940 PetscValidType(mat, 1); 1941 PetscAssertPointer(idxm, 3); 1942 PetscAssertPointer(idxn, 5); 1943 PetscAssertPointer(v, 6); 1944 1945 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1946 jdxm = buf; 1947 jdxn = buf + m; 1948 } else { 1949 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1950 jdxm = bufm; 1951 jdxn = bufn; 1952 } 1953 for (i = 0; i < m; i++) { 1954 for (j = 0; j < 3 - sdim; j++) dxm++; 1955 tmp = *dxm++ - starts[0]; 1956 for (j = 0; j < sdim - 1; j++) { 1957 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1958 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1959 } 1960 dxm++; 1961 jdxm[i] = tmp; 1962 } 1963 for (i = 0; i < n; i++) { 1964 for (j = 0; j < 3 - sdim; j++) dxn++; 1965 tmp = *dxn++ - starts[0]; 1966 for (j = 0; j < sdim - 1; j++) { 1967 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1968 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1969 } 1970 dxn++; 1971 jdxn[i] = tmp; 1972 } 1973 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1974 PetscCall(PetscFree2(bufm, bufn)); 1975 PetscFunctionReturn(PETSC_SUCCESS); 1976 } 1977 1978 /*@ 1979 MatSetStencil - Sets the grid information for setting values into a matrix via 1980 `MatSetValuesStencil()` 1981 1982 Not Collective 1983 1984 Input Parameters: 1985 + mat - the matrix 1986 . dim - dimension of the grid 1, 2, or 3 1987 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1988 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1989 - dof - number of degrees of freedom per node 1990 1991 Level: beginner 1992 1993 Notes: 1994 Inspired by the structured grid interface to the HYPRE package 1995 (www.llnl.gov/CASC/hyper) 1996 1997 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1998 user. 1999 2000 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 2001 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 2002 @*/ 2003 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 2004 { 2005 PetscFunctionBegin; 2006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2007 PetscAssertPointer(dims, 3); 2008 PetscAssertPointer(starts, 4); 2009 2010 mat->stencil.dim = dim + (dof > 1); 2011 for (PetscInt i = 0; i < dim; i++) { 2012 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2013 mat->stencil.starts[i] = starts[dim - i - 1]; 2014 } 2015 mat->stencil.dims[dim] = dof; 2016 mat->stencil.starts[dim] = 0; 2017 mat->stencil.noc = (PetscBool)(dof == 1); 2018 PetscFunctionReturn(PETSC_SUCCESS); 2019 } 2020 2021 /*@ 2022 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2023 2024 Not Collective 2025 2026 Input Parameters: 2027 + mat - the matrix 2028 . v - a logically two-dimensional array of values 2029 . m - the number of block rows 2030 . idxm - the global block indices 2031 . n - the number of block columns 2032 . idxn - the global block indices 2033 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2034 2035 Level: intermediate 2036 2037 Notes: 2038 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2039 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2040 2041 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2042 NOT the total number of rows/columns; for example, if the block size is 2 and 2043 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2044 The values in `idxm` would be 1 2; that is the first index for each block divided by 2045 the block size. 2046 2047 You must call `MatSetBlockSize()` when constructing this matrix (before 2048 preallocating it). 2049 2050 By default the values, `v`, are row-oriented, so the layout of 2051 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2052 2053 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2054 options cannot be mixed without intervening calls to the assembly 2055 routines. 2056 2057 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2058 as well as in C. 2059 2060 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2061 simply ignored. This allows easily inserting element stiffness matrices 2062 with homogeneous Dirichlet boundary conditions that you don't want represented 2063 in the matrix. 2064 2065 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2066 internal searching must be done to determine where to place the 2067 data in the matrix storage space. By instead inserting blocks of 2068 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2069 reduced. 2070 2071 Example: 2072 .vb 2073 Suppose m=n=2 and block size(bs) = 2 The array is 2074 2075 1 2 | 3 4 2076 5 6 | 7 8 2077 - - - | - - - 2078 9 10 | 11 12 2079 13 14 | 15 16 2080 2081 v[] should be passed in like 2082 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2083 2084 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2085 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2086 .ve 2087 2088 Fortran Notes: 2089 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2090 .vb 2091 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2092 .ve 2093 2094 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2095 2096 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2097 @*/ 2098 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2099 { 2100 PetscFunctionBeginHot; 2101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2102 PetscValidType(mat, 1); 2103 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2104 PetscAssertPointer(idxm, 3); 2105 PetscAssertPointer(idxn, 5); 2106 MatCheckPreallocated(mat, 1); 2107 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2108 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2109 if (PetscDefined(USE_DEBUG)) { 2110 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2111 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2112 } 2113 if (PetscDefined(USE_DEBUG)) { 2114 PetscInt rbs, cbs, M, N, i; 2115 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2116 PetscCall(MatGetSize(mat, &M, &N)); 2117 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); 2118 for (i = 0; i < n; i++) 2119 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); 2120 } 2121 if (mat->assembled) { 2122 mat->was_assembled = PETSC_TRUE; 2123 mat->assembled = PETSC_FALSE; 2124 } 2125 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2126 if (mat->ops->setvaluesblocked) { 2127 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2128 } else { 2129 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2130 PetscInt i, j, bs, cbs; 2131 2132 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2133 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2134 iidxm = buf; 2135 iidxn = buf + m * bs; 2136 } else { 2137 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2138 iidxm = bufr; 2139 iidxn = bufc; 2140 } 2141 for (i = 0; i < m; i++) { 2142 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2143 } 2144 if (m != n || bs != cbs || idxm != idxn) { 2145 for (i = 0; i < n; i++) { 2146 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2147 } 2148 } else iidxn = iidxm; 2149 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2150 PetscCall(PetscFree2(bufr, bufc)); 2151 } 2152 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2153 PetscFunctionReturn(PETSC_SUCCESS); 2154 } 2155 2156 /*@ 2157 MatGetValues - Gets a block of local values from a matrix. 2158 2159 Not Collective; can only return values that are owned by the give process 2160 2161 Input Parameters: 2162 + mat - the matrix 2163 . v - a logically two-dimensional array for storing the values 2164 . m - the number of rows 2165 . idxm - the global indices of the rows 2166 . n - the number of columns 2167 - idxn - the global indices of the columns 2168 2169 Level: advanced 2170 2171 Notes: 2172 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2173 The values, `v`, are then returned in a row-oriented format, 2174 analogous to that used by default in `MatSetValues()`. 2175 2176 `MatGetValues()` uses 0-based row and column numbers in 2177 Fortran as well as in C. 2178 2179 `MatGetValues()` requires that the matrix has been assembled 2180 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2181 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2182 without intermediate matrix assembly. 2183 2184 Negative row or column indices will be ignored and those locations in `v` will be 2185 left unchanged. 2186 2187 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2188 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2189 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2190 2191 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2192 @*/ 2193 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2194 { 2195 PetscFunctionBegin; 2196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2197 PetscValidType(mat, 1); 2198 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2199 PetscAssertPointer(idxm, 3); 2200 PetscAssertPointer(idxn, 5); 2201 PetscAssertPointer(v, 6); 2202 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2203 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2204 MatCheckPreallocated(mat, 1); 2205 2206 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2207 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2208 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2209 PetscFunctionReturn(PETSC_SUCCESS); 2210 } 2211 2212 /*@ 2213 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2214 defined previously by `MatSetLocalToGlobalMapping()` 2215 2216 Not Collective 2217 2218 Input Parameters: 2219 + mat - the matrix 2220 . nrow - number of rows 2221 . irow - the row local indices 2222 . ncol - number of columns 2223 - icol - the column local indices 2224 2225 Output Parameter: 2226 . y - a logically two-dimensional array of values 2227 2228 Level: advanced 2229 2230 Notes: 2231 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2232 2233 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, 2234 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2235 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2236 with `MatSetLocalToGlobalMapping()`. 2237 2238 Developer Note: 2239 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2240 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2241 2242 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2243 `MatSetValuesLocal()`, `MatGetValues()` 2244 @*/ 2245 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2246 { 2247 PetscFunctionBeginHot; 2248 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2249 PetscValidType(mat, 1); 2250 MatCheckPreallocated(mat, 1); 2251 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2252 PetscAssertPointer(irow, 3); 2253 PetscAssertPointer(icol, 5); 2254 if (PetscDefined(USE_DEBUG)) { 2255 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2256 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2257 } 2258 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2259 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2260 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2261 else { 2262 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2263 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2264 irowm = buf; 2265 icolm = buf + nrow; 2266 } else { 2267 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2268 irowm = bufr; 2269 icolm = bufc; 2270 } 2271 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2272 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2273 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2274 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2275 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2276 PetscCall(PetscFree2(bufr, bufc)); 2277 } 2278 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2279 PetscFunctionReturn(PETSC_SUCCESS); 2280 } 2281 2282 /*@ 2283 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2284 the same size. Currently, this can only be called once and creates the given matrix. 2285 2286 Not Collective 2287 2288 Input Parameters: 2289 + mat - the matrix 2290 . nb - the number of blocks 2291 . bs - the number of rows (and columns) in each block 2292 . rows - a concatenation of the rows for each block 2293 - v - a concatenation of logically two-dimensional arrays of values 2294 2295 Level: advanced 2296 2297 Notes: 2298 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2299 2300 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2301 2302 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2303 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2304 @*/ 2305 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2306 { 2307 PetscFunctionBegin; 2308 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2309 PetscValidType(mat, 1); 2310 PetscAssertPointer(rows, 4); 2311 PetscAssertPointer(v, 5); 2312 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2313 2314 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2315 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2316 else { 2317 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2318 } 2319 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2320 PetscFunctionReturn(PETSC_SUCCESS); 2321 } 2322 2323 /*@ 2324 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2325 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2326 using a local (per-processor) numbering. 2327 2328 Not Collective 2329 2330 Input Parameters: 2331 + x - the matrix 2332 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2333 - cmapping - column mapping 2334 2335 Level: intermediate 2336 2337 Note: 2338 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2339 2340 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2341 @*/ 2342 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2343 { 2344 PetscFunctionBegin; 2345 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2346 PetscValidType(x, 1); 2347 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2348 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2349 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2350 else { 2351 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2352 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2353 } 2354 PetscFunctionReturn(PETSC_SUCCESS); 2355 } 2356 2357 /*@ 2358 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2359 2360 Not Collective 2361 2362 Input Parameter: 2363 . A - the matrix 2364 2365 Output Parameters: 2366 + rmapping - row mapping 2367 - cmapping - column mapping 2368 2369 Level: advanced 2370 2371 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2372 @*/ 2373 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2374 { 2375 PetscFunctionBegin; 2376 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2377 PetscValidType(A, 1); 2378 if (rmapping) { 2379 PetscAssertPointer(rmapping, 2); 2380 *rmapping = A->rmap->mapping; 2381 } 2382 if (cmapping) { 2383 PetscAssertPointer(cmapping, 3); 2384 *cmapping = A->cmap->mapping; 2385 } 2386 PetscFunctionReturn(PETSC_SUCCESS); 2387 } 2388 2389 /*@ 2390 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2391 2392 Logically Collective 2393 2394 Input Parameters: 2395 + A - the matrix 2396 . rmap - row layout 2397 - cmap - column layout 2398 2399 Level: advanced 2400 2401 Note: 2402 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2403 2404 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2405 @*/ 2406 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2407 { 2408 PetscFunctionBegin; 2409 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2410 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2411 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2412 PetscFunctionReturn(PETSC_SUCCESS); 2413 } 2414 2415 /*@ 2416 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2417 2418 Not Collective 2419 2420 Input Parameter: 2421 . A - the matrix 2422 2423 Output Parameters: 2424 + rmap - row layout 2425 - cmap - column layout 2426 2427 Level: advanced 2428 2429 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2430 @*/ 2431 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2432 { 2433 PetscFunctionBegin; 2434 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2435 PetscValidType(A, 1); 2436 if (rmap) { 2437 PetscAssertPointer(rmap, 2); 2438 *rmap = A->rmap; 2439 } 2440 if (cmap) { 2441 PetscAssertPointer(cmap, 3); 2442 *cmap = A->cmap; 2443 } 2444 PetscFunctionReturn(PETSC_SUCCESS); 2445 } 2446 2447 /*@ 2448 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2449 using a local numbering of the rows and columns. 2450 2451 Not Collective 2452 2453 Input Parameters: 2454 + mat - the matrix 2455 . nrow - number of rows 2456 . irow - the row local indices 2457 . ncol - number of columns 2458 . icol - the column local indices 2459 . y - a logically two-dimensional array of values 2460 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2461 2462 Level: intermediate 2463 2464 Notes: 2465 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2466 2467 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2468 options cannot be mixed without intervening calls to the assembly 2469 routines. 2470 2471 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2472 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2473 2474 Fortran Notes: 2475 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2476 .vb 2477 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2478 .ve 2479 2480 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2481 2482 Developer Note: 2483 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2484 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2485 2486 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2487 `MatGetValuesLocal()` 2488 @*/ 2489 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2490 { 2491 PetscFunctionBeginHot; 2492 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2493 PetscValidType(mat, 1); 2494 MatCheckPreallocated(mat, 1); 2495 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2496 PetscAssertPointer(irow, 3); 2497 PetscAssertPointer(icol, 5); 2498 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2499 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2500 if (PetscDefined(USE_DEBUG)) { 2501 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2502 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2503 } 2504 2505 if (mat->assembled) { 2506 mat->was_assembled = PETSC_TRUE; 2507 mat->assembled = PETSC_FALSE; 2508 } 2509 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2510 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2511 else { 2512 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2513 const PetscInt *irowm, *icolm; 2514 2515 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2516 bufr = buf; 2517 bufc = buf + nrow; 2518 irowm = bufr; 2519 icolm = bufc; 2520 } else { 2521 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2522 irowm = bufr; 2523 icolm = bufc; 2524 } 2525 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2526 else irowm = irow; 2527 if (mat->cmap->mapping) { 2528 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2529 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2530 } else icolm = irowm; 2531 } else icolm = icol; 2532 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2533 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2534 } 2535 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2536 PetscFunctionReturn(PETSC_SUCCESS); 2537 } 2538 2539 /*@ 2540 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2541 using a local ordering of the nodes a block at a time. 2542 2543 Not Collective 2544 2545 Input Parameters: 2546 + mat - the matrix 2547 . nrow - number of rows 2548 . irow - the row local indices 2549 . ncol - number of columns 2550 . icol - the column local indices 2551 . y - a logically two-dimensional array of values 2552 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2553 2554 Level: intermediate 2555 2556 Notes: 2557 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2558 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2559 2560 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2561 options cannot be mixed without intervening calls to the assembly 2562 routines. 2563 2564 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2565 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2566 2567 Fortran Notes: 2568 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2569 .vb 2570 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2571 .ve 2572 2573 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2574 2575 Developer Note: 2576 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2577 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2578 2579 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2580 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2581 @*/ 2582 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2583 { 2584 PetscFunctionBeginHot; 2585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2586 PetscValidType(mat, 1); 2587 MatCheckPreallocated(mat, 1); 2588 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2589 PetscAssertPointer(irow, 3); 2590 PetscAssertPointer(icol, 5); 2591 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2592 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2593 if (PetscDefined(USE_DEBUG)) { 2594 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2595 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); 2596 } 2597 2598 if (mat->assembled) { 2599 mat->was_assembled = PETSC_TRUE; 2600 mat->assembled = PETSC_FALSE; 2601 } 2602 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2603 PetscInt irbs, rbs; 2604 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2605 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2606 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2607 } 2608 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2609 PetscInt icbs, cbs; 2610 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2611 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2612 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2613 } 2614 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2615 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2616 else { 2617 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2618 const PetscInt *irowm, *icolm; 2619 2620 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2621 bufr = buf; 2622 bufc = buf + nrow; 2623 irowm = bufr; 2624 icolm = bufc; 2625 } else { 2626 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2627 irowm = bufr; 2628 icolm = bufc; 2629 } 2630 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2631 else irowm = irow; 2632 if (mat->cmap->mapping) { 2633 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2634 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2635 } else icolm = irowm; 2636 } else icolm = icol; 2637 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2638 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2639 } 2640 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2641 PetscFunctionReturn(PETSC_SUCCESS); 2642 } 2643 2644 /*@ 2645 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2646 2647 Collective 2648 2649 Input Parameters: 2650 + mat - the matrix 2651 - x - the vector to be multiplied 2652 2653 Output Parameter: 2654 . y - the result 2655 2656 Level: developer 2657 2658 Note: 2659 The vectors `x` and `y` cannot be the same. I.e., one cannot 2660 call `MatMultDiagonalBlock`(A,y,y). 2661 2662 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2663 @*/ 2664 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2665 { 2666 PetscFunctionBegin; 2667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2668 PetscValidType(mat, 1); 2669 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2670 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2671 2672 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2673 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2674 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2675 MatCheckPreallocated(mat, 1); 2676 2677 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2678 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2679 PetscFunctionReturn(PETSC_SUCCESS); 2680 } 2681 2682 /*@ 2683 MatMult - Computes the matrix-vector product, $y = Ax$. 2684 2685 Neighbor-wise Collective 2686 2687 Input Parameters: 2688 + mat - the matrix 2689 - x - the vector to be multiplied 2690 2691 Output Parameter: 2692 . y - the result 2693 2694 Level: beginner 2695 2696 Note: 2697 The vectors `x` and `y` cannot be the same. I.e., one cannot 2698 call `MatMult`(A,y,y). 2699 2700 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2701 @*/ 2702 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2703 { 2704 PetscFunctionBegin; 2705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2706 PetscValidType(mat, 1); 2707 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2708 VecCheckAssembled(x); 2709 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2710 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2711 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2712 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2713 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); 2714 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); 2715 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); 2716 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); 2717 PetscCall(VecSetErrorIfLocked(y, 3)); 2718 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2719 MatCheckPreallocated(mat, 1); 2720 2721 PetscCall(VecLockReadPush(x)); 2722 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2723 PetscUseTypeMethod(mat, mult, x, y); 2724 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2725 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2726 PetscCall(VecLockReadPop(x)); 2727 PetscFunctionReturn(PETSC_SUCCESS); 2728 } 2729 2730 /*@ 2731 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2732 2733 Neighbor-wise Collective 2734 2735 Input Parameters: 2736 + mat - the matrix 2737 - x - the vector to be multiplied 2738 2739 Output Parameter: 2740 . y - the result 2741 2742 Level: beginner 2743 2744 Notes: 2745 The vectors `x` and `y` cannot be the same. I.e., one cannot 2746 call `MatMultTranspose`(A,y,y). 2747 2748 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2749 use `MatMultHermitianTranspose()` 2750 2751 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2752 @*/ 2753 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2754 { 2755 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2756 2757 PetscFunctionBegin; 2758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2759 PetscValidType(mat, 1); 2760 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2761 VecCheckAssembled(x); 2762 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2763 2764 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2765 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2766 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2767 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2768 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2769 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2770 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2771 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2772 MatCheckPreallocated(mat, 1); 2773 2774 if (!mat->ops->multtranspose) { 2775 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2776 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); 2777 } else op = mat->ops->multtranspose; 2778 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2779 PetscCall(VecLockReadPush(x)); 2780 PetscCall((*op)(mat, x, y)); 2781 PetscCall(VecLockReadPop(x)); 2782 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2783 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2784 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2785 PetscFunctionReturn(PETSC_SUCCESS); 2786 } 2787 2788 /*@ 2789 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2790 2791 Neighbor-wise Collective 2792 2793 Input Parameters: 2794 + mat - the matrix 2795 - x - the vector to be multiplied 2796 2797 Output Parameter: 2798 . y - the result 2799 2800 Level: beginner 2801 2802 Notes: 2803 The vectors `x` and `y` cannot be the same. I.e., one cannot 2804 call `MatMultHermitianTranspose`(A,y,y). 2805 2806 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2807 2808 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2809 2810 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2811 @*/ 2812 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2813 { 2814 PetscFunctionBegin; 2815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2816 PetscValidType(mat, 1); 2817 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2818 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2819 2820 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2821 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2822 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2823 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); 2824 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); 2825 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); 2826 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); 2827 MatCheckPreallocated(mat, 1); 2828 2829 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2830 #if defined(PETSC_USE_COMPLEX) 2831 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2832 PetscCall(VecLockReadPush(x)); 2833 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2834 else PetscUseTypeMethod(mat, mult, x, y); 2835 PetscCall(VecLockReadPop(x)); 2836 } else { 2837 Vec w; 2838 PetscCall(VecDuplicate(x, &w)); 2839 PetscCall(VecCopy(x, w)); 2840 PetscCall(VecConjugate(w)); 2841 PetscCall(MatMultTranspose(mat, w, y)); 2842 PetscCall(VecDestroy(&w)); 2843 PetscCall(VecConjugate(y)); 2844 } 2845 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2846 #else 2847 PetscCall(MatMultTranspose(mat, x, y)); 2848 #endif 2849 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2850 PetscFunctionReturn(PETSC_SUCCESS); 2851 } 2852 2853 /*@ 2854 MatMultAdd - Computes $v3 = v2 + A * v1$. 2855 2856 Neighbor-wise Collective 2857 2858 Input Parameters: 2859 + mat - the matrix 2860 . v1 - the vector to be multiplied by `mat` 2861 - v2 - the vector to be added to the result 2862 2863 Output Parameter: 2864 . v3 - the result 2865 2866 Level: beginner 2867 2868 Note: 2869 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2870 call `MatMultAdd`(A,v1,v2,v1). 2871 2872 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2873 @*/ 2874 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2875 { 2876 PetscFunctionBegin; 2877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2878 PetscValidType(mat, 1); 2879 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2880 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2881 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2882 2883 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2884 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2885 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); 2886 /* 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); 2887 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); */ 2888 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); 2889 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); 2890 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2891 MatCheckPreallocated(mat, 1); 2892 2893 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2894 PetscCall(VecLockReadPush(v1)); 2895 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2896 PetscCall(VecLockReadPop(v1)); 2897 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2898 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2899 PetscFunctionReturn(PETSC_SUCCESS); 2900 } 2901 2902 /*@ 2903 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2904 2905 Neighbor-wise Collective 2906 2907 Input Parameters: 2908 + mat - the matrix 2909 . v1 - the vector to be multiplied by the transpose of the matrix 2910 - v2 - the vector to be added to the result 2911 2912 Output Parameter: 2913 . v3 - the result 2914 2915 Level: beginner 2916 2917 Note: 2918 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2919 call `MatMultTransposeAdd`(A,v1,v2,v1). 2920 2921 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2922 @*/ 2923 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2924 { 2925 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2926 2927 PetscFunctionBegin; 2928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2929 PetscValidType(mat, 1); 2930 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2931 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2932 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2933 2934 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2935 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2936 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); 2937 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); 2938 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); 2939 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2940 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2941 MatCheckPreallocated(mat, 1); 2942 2943 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2944 PetscCall(VecLockReadPush(v1)); 2945 PetscCall((*op)(mat, v1, v2, v3)); 2946 PetscCall(VecLockReadPop(v1)); 2947 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2948 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2949 PetscFunctionReturn(PETSC_SUCCESS); 2950 } 2951 2952 /*@ 2953 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2954 2955 Neighbor-wise Collective 2956 2957 Input Parameters: 2958 + mat - the matrix 2959 . v1 - the vector to be multiplied by the Hermitian transpose 2960 - v2 - the vector to be added to the result 2961 2962 Output Parameter: 2963 . v3 - the result 2964 2965 Level: beginner 2966 2967 Note: 2968 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2969 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2970 2971 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2972 @*/ 2973 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2974 { 2975 PetscFunctionBegin; 2976 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2977 PetscValidType(mat, 1); 2978 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2979 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2980 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2981 2982 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2983 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2984 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2985 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); 2986 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); 2987 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); 2988 MatCheckPreallocated(mat, 1); 2989 2990 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2991 PetscCall(VecLockReadPush(v1)); 2992 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2993 else { 2994 Vec w, z; 2995 PetscCall(VecDuplicate(v1, &w)); 2996 PetscCall(VecCopy(v1, w)); 2997 PetscCall(VecConjugate(w)); 2998 PetscCall(VecDuplicate(v3, &z)); 2999 PetscCall(MatMultTranspose(mat, w, z)); 3000 PetscCall(VecDestroy(&w)); 3001 PetscCall(VecConjugate(z)); 3002 if (v2 != v3) { 3003 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 3004 } else { 3005 PetscCall(VecAXPY(v3, 1.0, z)); 3006 } 3007 PetscCall(VecDestroy(&z)); 3008 } 3009 PetscCall(VecLockReadPop(v1)); 3010 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 3011 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 3012 PetscFunctionReturn(PETSC_SUCCESS); 3013 } 3014 3015 /*@ 3016 MatGetFactorType - gets the type of factorization a matrix is 3017 3018 Not Collective 3019 3020 Input Parameter: 3021 . mat - the matrix 3022 3023 Output Parameter: 3024 . 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` 3025 3026 Level: intermediate 3027 3028 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3029 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3030 @*/ 3031 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3032 { 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 PetscValidType(mat, 1); 3036 PetscAssertPointer(t, 2); 3037 *t = mat->factortype; 3038 PetscFunctionReturn(PETSC_SUCCESS); 3039 } 3040 3041 /*@ 3042 MatSetFactorType - sets the type of factorization a matrix is 3043 3044 Logically Collective 3045 3046 Input Parameters: 3047 + mat - the matrix 3048 - 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` 3049 3050 Level: intermediate 3051 3052 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3053 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3054 @*/ 3055 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3056 { 3057 PetscFunctionBegin; 3058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3059 PetscValidType(mat, 1); 3060 mat->factortype = t; 3061 PetscFunctionReturn(PETSC_SUCCESS); 3062 } 3063 3064 /*@ 3065 MatGetInfo - Returns information about matrix storage (number of 3066 nonzeros, memory, etc.). 3067 3068 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3069 3070 Input Parameters: 3071 + mat - the matrix 3072 - 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) 3073 3074 Output Parameter: 3075 . info - matrix information context 3076 3077 Options Database Key: 3078 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3079 3080 Level: intermediate 3081 3082 Notes: 3083 The `MatInfo` context contains a variety of matrix data, including 3084 number of nonzeros allocated and used, number of mallocs during 3085 matrix assembly, etc. Additional information for factored matrices 3086 is provided (such as the fill ratio, number of mallocs during 3087 factorization, etc.). 3088 3089 Example: 3090 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3091 data within the `MatInfo` context. For example, 3092 .vb 3093 MatInfo info; 3094 Mat A; 3095 double mal, nz_a, nz_u; 3096 3097 MatGetInfo(A, MAT_LOCAL, &info); 3098 mal = info.mallocs; 3099 nz_a = info.nz_allocated; 3100 .ve 3101 3102 Fortran Note: 3103 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3104 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3105 a complete list of parameter names. 3106 .vb 3107 MatInfo info(MAT_INFO_SIZE) 3108 double precision mal, nz_a 3109 Mat A 3110 integer ierr 3111 3112 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3113 mal = info(MAT_INFO_MALLOCS) 3114 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3115 .ve 3116 3117 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3118 @*/ 3119 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3120 { 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3123 PetscValidType(mat, 1); 3124 PetscAssertPointer(info, 3); 3125 MatCheckPreallocated(mat, 1); 3126 PetscUseTypeMethod(mat, getinfo, flag, info); 3127 PetscFunctionReturn(PETSC_SUCCESS); 3128 } 3129 3130 /* 3131 This is used by external packages where it is not easy to get the info from the actual 3132 matrix factorization. 3133 */ 3134 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3135 { 3136 PetscFunctionBegin; 3137 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3138 PetscFunctionReturn(PETSC_SUCCESS); 3139 } 3140 3141 /*@ 3142 MatLUFactor - Performs in-place LU factorization of matrix. 3143 3144 Collective 3145 3146 Input Parameters: 3147 + mat - the matrix 3148 . row - row permutation 3149 . col - column permutation 3150 - info - options for factorization, includes 3151 .vb 3152 fill - expected fill as ratio of original fill. 3153 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3154 Run with the option -info to determine an optimal value to use 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 This changes the state of the matrix to a factored matrix; it cannot be used 3165 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3166 3167 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3168 when not using `KSP`. 3169 3170 Developer Note: 3171 The Fortran interface is not autogenerated as the 3172 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3173 3174 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3175 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3176 @*/ 3177 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3178 { 3179 MatFactorInfo tinfo; 3180 3181 PetscFunctionBegin; 3182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3183 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3184 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3185 if (info) PetscAssertPointer(info, 4); 3186 PetscValidType(mat, 1); 3187 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3188 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3189 MatCheckPreallocated(mat, 1); 3190 if (!info) { 3191 PetscCall(MatFactorInfoInitialize(&tinfo)); 3192 info = &tinfo; 3193 } 3194 3195 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3196 PetscUseTypeMethod(mat, lufactor, row, col, info); 3197 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3198 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3199 PetscFunctionReturn(PETSC_SUCCESS); 3200 } 3201 3202 /*@ 3203 MatILUFactor - Performs in-place ILU factorization of matrix. 3204 3205 Collective 3206 3207 Input Parameters: 3208 + mat - the matrix 3209 . row - row permutation 3210 . col - column permutation 3211 - info - structure containing 3212 .vb 3213 levels - number of levels of fill. 3214 expected fill - as ratio of original fill. 3215 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3216 missing diagonal entries) 3217 .ve 3218 3219 Level: developer 3220 3221 Notes: 3222 Most users should employ the `KSP` interface for linear solvers 3223 instead of working directly with matrix algebra routines such as this. 3224 See, e.g., `KSPCreate()`. 3225 3226 Probably really in-place only when level of fill is zero, otherwise allocates 3227 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3228 when not using `KSP`. 3229 3230 Developer Note: 3231 The Fortran interface is not autogenerated as the 3232 interface definition cannot be generated correctly [due to MatFactorInfo] 3233 3234 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3235 @*/ 3236 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3237 { 3238 PetscFunctionBegin; 3239 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3240 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3241 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3242 PetscAssertPointer(info, 4); 3243 PetscValidType(mat, 1); 3244 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3245 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3246 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3247 MatCheckPreallocated(mat, 1); 3248 3249 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3250 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3251 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3252 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3253 PetscFunctionReturn(PETSC_SUCCESS); 3254 } 3255 3256 /*@ 3257 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3258 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3259 3260 Collective 3261 3262 Input Parameters: 3263 + fact - the factor matrix obtained with `MatGetFactor()` 3264 . mat - the matrix 3265 . row - the row permutation 3266 . col - the column permutation 3267 - info - options for factorization, includes 3268 .vb 3269 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3270 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3271 .ve 3272 3273 Level: developer 3274 3275 Notes: 3276 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3277 3278 Most users should employ the simplified `KSP` interface for linear solvers 3279 instead of working directly with matrix algebra routines such as this. 3280 See, e.g., `KSPCreate()`. 3281 3282 Developer Note: 3283 The Fortran interface is not autogenerated as the 3284 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3285 3286 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3287 @*/ 3288 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3289 { 3290 MatFactorInfo tinfo; 3291 3292 PetscFunctionBegin; 3293 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3294 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3295 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3296 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3297 if (info) PetscAssertPointer(info, 5); 3298 PetscValidType(fact, 1); 3299 PetscValidType(mat, 2); 3300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3301 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3302 MatCheckPreallocated(mat, 2); 3303 if (!info) { 3304 PetscCall(MatFactorInfoInitialize(&tinfo)); 3305 info = &tinfo; 3306 } 3307 3308 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3309 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3310 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3311 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3312 PetscFunctionReturn(PETSC_SUCCESS); 3313 } 3314 3315 /*@ 3316 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3317 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3318 3319 Collective 3320 3321 Input Parameters: 3322 + fact - the factor matrix obtained with `MatGetFactor()` 3323 . mat - the matrix 3324 - info - options for factorization 3325 3326 Level: developer 3327 3328 Notes: 3329 See `MatLUFactor()` for in-place factorization. See 3330 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3331 3332 Most users should employ the `KSP` interface for linear solvers 3333 instead of working directly with matrix algebra routines such as this. 3334 See, e.g., `KSPCreate()`. 3335 3336 Developer Note: 3337 The Fortran interface is not autogenerated as the 3338 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3339 3340 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3341 @*/ 3342 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3343 { 3344 MatFactorInfo tinfo; 3345 3346 PetscFunctionBegin; 3347 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3348 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3349 PetscValidType(fact, 1); 3350 PetscValidType(mat, 2); 3351 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3352 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, 3353 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3354 3355 MatCheckPreallocated(mat, 2); 3356 if (!info) { 3357 PetscCall(MatFactorInfoInitialize(&tinfo)); 3358 info = &tinfo; 3359 } 3360 3361 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3362 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3363 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3364 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3365 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3366 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3367 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3368 PetscFunctionReturn(PETSC_SUCCESS); 3369 } 3370 3371 /*@ 3372 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3373 symmetric matrix. 3374 3375 Collective 3376 3377 Input Parameters: 3378 + mat - the matrix 3379 . perm - row and column permutations 3380 - info - expected fill as ratio of original fill 3381 3382 Level: developer 3383 3384 Notes: 3385 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3386 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3387 3388 Most users should employ the `KSP` interface for linear solvers 3389 instead of working directly with matrix algebra routines such as this. 3390 See, e.g., `KSPCreate()`. 3391 3392 Developer Note: 3393 The Fortran interface is not autogenerated as the 3394 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3395 3396 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3397 `MatGetOrdering()` 3398 @*/ 3399 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3400 { 3401 MatFactorInfo tinfo; 3402 3403 PetscFunctionBegin; 3404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3405 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3406 if (info) PetscAssertPointer(info, 3); 3407 PetscValidType(mat, 1); 3408 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3409 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3410 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3411 MatCheckPreallocated(mat, 1); 3412 if (!info) { 3413 PetscCall(MatFactorInfoInitialize(&tinfo)); 3414 info = &tinfo; 3415 } 3416 3417 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3418 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3419 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3420 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3421 PetscFunctionReturn(PETSC_SUCCESS); 3422 } 3423 3424 /*@ 3425 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3426 of a symmetric matrix. 3427 3428 Collective 3429 3430 Input Parameters: 3431 + fact - the factor matrix obtained with `MatGetFactor()` 3432 . mat - the matrix 3433 . perm - row and column permutations 3434 - info - options for factorization, includes 3435 .vb 3436 fill - expected fill as ratio of original fill. 3437 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3438 Run with the option -info to determine an optimal value to use 3439 .ve 3440 3441 Level: developer 3442 3443 Notes: 3444 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3445 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3446 3447 Most users should employ the `KSP` interface for linear solvers 3448 instead of working directly with matrix algebra routines such as this. 3449 See, e.g., `KSPCreate()`. 3450 3451 Developer Note: 3452 The Fortran interface is not autogenerated as the 3453 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3454 3455 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3456 `MatGetOrdering()` 3457 @*/ 3458 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3459 { 3460 MatFactorInfo tinfo; 3461 3462 PetscFunctionBegin; 3463 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3464 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3465 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3466 if (info) PetscAssertPointer(info, 4); 3467 PetscValidType(fact, 1); 3468 PetscValidType(mat, 2); 3469 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3470 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3471 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3472 MatCheckPreallocated(mat, 2); 3473 if (!info) { 3474 PetscCall(MatFactorInfoInitialize(&tinfo)); 3475 info = &tinfo; 3476 } 3477 3478 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3479 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3480 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3481 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3482 PetscFunctionReturn(PETSC_SUCCESS); 3483 } 3484 3485 /*@ 3486 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3487 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3488 `MatCholeskyFactorSymbolic()`. 3489 3490 Collective 3491 3492 Input Parameters: 3493 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3494 . mat - the initial matrix that is to be factored 3495 - info - options for factorization 3496 3497 Level: developer 3498 3499 Note: 3500 Most users should employ the `KSP` interface for linear solvers 3501 instead of working directly with matrix algebra routines such as this. 3502 See, e.g., `KSPCreate()`. 3503 3504 Developer Note: 3505 The Fortran interface is not autogenerated as the 3506 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3507 3508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3509 @*/ 3510 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3511 { 3512 MatFactorInfo tinfo; 3513 3514 PetscFunctionBegin; 3515 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3517 PetscValidType(fact, 1); 3518 PetscValidType(mat, 2); 3519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3520 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, 3521 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3522 MatCheckPreallocated(mat, 2); 3523 if (!info) { 3524 PetscCall(MatFactorInfoInitialize(&tinfo)); 3525 info = &tinfo; 3526 } 3527 3528 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3529 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3530 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3531 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3532 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3533 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3534 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3535 PetscFunctionReturn(PETSC_SUCCESS); 3536 } 3537 3538 /*@ 3539 MatQRFactor - Performs in-place QR factorization of matrix. 3540 3541 Collective 3542 3543 Input Parameters: 3544 + mat - the matrix 3545 . col - column permutation 3546 - info - options for factorization, includes 3547 .vb 3548 fill - expected fill as ratio of original fill. 3549 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3550 Run with the option -info to determine an optimal value to use 3551 .ve 3552 3553 Level: developer 3554 3555 Notes: 3556 Most users should employ the `KSP` interface for linear solvers 3557 instead of working directly with matrix algebra routines such as this. 3558 See, e.g., `KSPCreate()`. 3559 3560 This changes the state of the matrix to a factored matrix; it cannot be used 3561 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3562 3563 Developer Note: 3564 The Fortran interface is not autogenerated as the 3565 interface definition cannot be generated correctly [due to MatFactorInfo] 3566 3567 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3568 `MatSetUnfactored()` 3569 @*/ 3570 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3571 { 3572 PetscFunctionBegin; 3573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3574 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3575 if (info) PetscAssertPointer(info, 3); 3576 PetscValidType(mat, 1); 3577 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3578 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3579 MatCheckPreallocated(mat, 1); 3580 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3581 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3582 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3583 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3584 PetscFunctionReturn(PETSC_SUCCESS); 3585 } 3586 3587 /*@ 3588 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3589 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3590 3591 Collective 3592 3593 Input Parameters: 3594 + fact - the factor matrix obtained with `MatGetFactor()` 3595 . mat - the matrix 3596 . col - column permutation 3597 - info - options for factorization, includes 3598 .vb 3599 fill - expected fill as ratio of original fill. 3600 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3601 Run with the option -info to determine an optimal value to use 3602 .ve 3603 3604 Level: developer 3605 3606 Note: 3607 Most users should employ the `KSP` interface for linear solvers 3608 instead of working directly with matrix algebra routines such as this. 3609 See, e.g., `KSPCreate()`. 3610 3611 Developer Note: 3612 The Fortran interface is not autogenerated as the 3613 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3614 3615 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3616 @*/ 3617 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3618 { 3619 MatFactorInfo tinfo; 3620 3621 PetscFunctionBegin; 3622 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3623 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3624 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3625 if (info) PetscAssertPointer(info, 4); 3626 PetscValidType(fact, 1); 3627 PetscValidType(mat, 2); 3628 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3629 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3630 MatCheckPreallocated(mat, 2); 3631 if (!info) { 3632 PetscCall(MatFactorInfoInitialize(&tinfo)); 3633 info = &tinfo; 3634 } 3635 3636 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3637 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3638 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3639 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3640 PetscFunctionReturn(PETSC_SUCCESS); 3641 } 3642 3643 /*@ 3644 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3645 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3646 3647 Collective 3648 3649 Input Parameters: 3650 + fact - the factor matrix obtained with `MatGetFactor()` 3651 . mat - the matrix 3652 - info - options for factorization 3653 3654 Level: developer 3655 3656 Notes: 3657 See `MatQRFactor()` for in-place factorization. 3658 3659 Most users should employ the `KSP` interface for linear solvers 3660 instead of working directly with matrix algebra routines such as this. 3661 See, e.g., `KSPCreate()`. 3662 3663 Developer Note: 3664 The Fortran interface is not autogenerated as the 3665 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3666 3667 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3668 @*/ 3669 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3670 { 3671 MatFactorInfo tinfo; 3672 3673 PetscFunctionBegin; 3674 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3676 PetscValidType(fact, 1); 3677 PetscValidType(mat, 2); 3678 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3679 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, 3680 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3681 3682 MatCheckPreallocated(mat, 2); 3683 if (!info) { 3684 PetscCall(MatFactorInfoInitialize(&tinfo)); 3685 info = &tinfo; 3686 } 3687 3688 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3689 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3690 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3691 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3692 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3693 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3694 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3695 PetscFunctionReturn(PETSC_SUCCESS); 3696 } 3697 3698 /*@ 3699 MatSolve - Solves $A x = b$, given a factored matrix. 3700 3701 Neighbor-wise Collective 3702 3703 Input Parameters: 3704 + mat - the factored matrix 3705 - b - the right-hand-side vector 3706 3707 Output Parameter: 3708 . x - the result vector 3709 3710 Level: developer 3711 3712 Notes: 3713 The vectors `b` and `x` cannot be the same. I.e., one cannot 3714 call `MatSolve`(A,x,x). 3715 3716 Most users should employ the `KSP` interface for linear solvers 3717 instead of working directly with matrix algebra routines such as this. 3718 See, e.g., `KSPCreate()`. 3719 3720 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3721 @*/ 3722 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3723 { 3724 PetscFunctionBegin; 3725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3726 PetscValidType(mat, 1); 3727 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3728 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3729 PetscCheckSameComm(mat, 1, b, 2); 3730 PetscCheckSameComm(mat, 1, x, 3); 3731 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3732 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); 3733 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); 3734 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); 3735 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3736 MatCheckPreallocated(mat, 1); 3737 3738 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3739 PetscCall(VecFlag(x, mat->factorerrortype)); 3740 if (mat->factorerrortype) { 3741 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3742 } else PetscUseTypeMethod(mat, solve, b, x); 3743 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3744 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3745 PetscFunctionReturn(PETSC_SUCCESS); 3746 } 3747 3748 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3749 { 3750 Vec b, x; 3751 PetscInt N, i; 3752 PetscErrorCode (*f)(Mat, Vec, Vec); 3753 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3754 3755 PetscFunctionBegin; 3756 if (A->factorerrortype) { 3757 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3758 PetscCall(MatSetInf(X)); 3759 PetscFunctionReturn(PETSC_SUCCESS); 3760 } 3761 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3762 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3763 PetscCall(MatBoundToCPU(A, &Abound)); 3764 if (!Abound) { 3765 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3766 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3767 } 3768 #if PetscDefined(HAVE_CUDA) 3769 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3770 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3771 #elif PetscDefined(HAVE_HIP) 3772 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3773 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3774 #endif 3775 PetscCall(MatGetSize(B, NULL, &N)); 3776 for (i = 0; i < N; i++) { 3777 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3778 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3779 PetscCall((*f)(A, b, x)); 3780 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3781 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3782 } 3783 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3784 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3785 PetscFunctionReturn(PETSC_SUCCESS); 3786 } 3787 3788 /*@ 3789 MatMatSolve - Solves $A X = B$, given a factored matrix. 3790 3791 Neighbor-wise Collective 3792 3793 Input Parameters: 3794 + A - the factored matrix 3795 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3796 3797 Output Parameter: 3798 . X - the result matrix (dense matrix) 3799 3800 Level: developer 3801 3802 Note: 3803 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3804 otherwise, `B` and `X` cannot be the same. 3805 3806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3807 @*/ 3808 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3809 { 3810 PetscFunctionBegin; 3811 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3812 PetscValidType(A, 1); 3813 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3814 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3815 PetscCheckSameComm(A, 1, B, 2); 3816 PetscCheckSameComm(A, 1, X, 3); 3817 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); 3818 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); 3819 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"); 3820 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3821 MatCheckPreallocated(A, 1); 3822 3823 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3824 if (!A->ops->matsolve) { 3825 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3826 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3827 } else PetscUseTypeMethod(A, matsolve, B, X); 3828 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3829 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3830 PetscFunctionReturn(PETSC_SUCCESS); 3831 } 3832 3833 /*@ 3834 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3835 3836 Neighbor-wise Collective 3837 3838 Input Parameters: 3839 + A - the factored matrix 3840 - B - the right-hand-side matrix (`MATDENSE` matrix) 3841 3842 Output Parameter: 3843 . X - the result matrix (dense matrix) 3844 3845 Level: developer 3846 3847 Note: 3848 The matrices `B` and `X` cannot be the same. I.e., one cannot 3849 call `MatMatSolveTranspose`(A,X,X). 3850 3851 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3852 @*/ 3853 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3854 { 3855 PetscFunctionBegin; 3856 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3857 PetscValidType(A, 1); 3858 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3859 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3860 PetscCheckSameComm(A, 1, B, 2); 3861 PetscCheckSameComm(A, 1, X, 3); 3862 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3863 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); 3864 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); 3865 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); 3866 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"); 3867 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3868 MatCheckPreallocated(A, 1); 3869 3870 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3871 if (!A->ops->matsolvetranspose) { 3872 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3873 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3874 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3875 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3876 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3877 PetscFunctionReturn(PETSC_SUCCESS); 3878 } 3879 3880 /*@ 3881 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3882 3883 Neighbor-wise Collective 3884 3885 Input Parameters: 3886 + A - the factored matrix 3887 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3888 3889 Output Parameter: 3890 . X - the result matrix (dense matrix) 3891 3892 Level: developer 3893 3894 Note: 3895 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 3896 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3897 3898 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3899 @*/ 3900 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3901 { 3902 PetscFunctionBegin; 3903 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3904 PetscValidType(A, 1); 3905 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3906 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3907 PetscCheckSameComm(A, 1, Bt, 2); 3908 PetscCheckSameComm(A, 1, X, 3); 3909 3910 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3911 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); 3912 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); 3913 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"); 3914 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3915 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3916 MatCheckPreallocated(A, 1); 3917 3918 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3919 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3920 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3921 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3922 PetscFunctionReturn(PETSC_SUCCESS); 3923 } 3924 3925 /*@ 3926 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3927 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3928 3929 Neighbor-wise Collective 3930 3931 Input Parameters: 3932 + mat - the factored matrix 3933 - b - the right-hand-side vector 3934 3935 Output Parameter: 3936 . x - the result vector 3937 3938 Level: developer 3939 3940 Notes: 3941 `MatSolve()` should be used for most applications, as it performs 3942 a forward solve followed by a backward solve. 3943 3944 The vectors `b` and `x` cannot be the same, i.e., one cannot 3945 call `MatForwardSolve`(A,x,x). 3946 3947 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3948 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3949 `MatForwardSolve()` solves $U^T*D y = b$, and 3950 `MatBackwardSolve()` solves $U x = y$. 3951 Thus they do not provide a symmetric preconditioner. 3952 3953 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3954 @*/ 3955 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3956 { 3957 PetscFunctionBegin; 3958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3959 PetscValidType(mat, 1); 3960 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3961 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3962 PetscCheckSameComm(mat, 1, b, 2); 3963 PetscCheckSameComm(mat, 1, x, 3); 3964 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3965 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); 3966 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); 3967 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); 3968 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3969 MatCheckPreallocated(mat, 1); 3970 3971 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3972 PetscUseTypeMethod(mat, forwardsolve, b, x); 3973 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3974 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3975 PetscFunctionReturn(PETSC_SUCCESS); 3976 } 3977 3978 /*@ 3979 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3980 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3981 3982 Neighbor-wise Collective 3983 3984 Input Parameters: 3985 + mat - the factored matrix 3986 - b - the right-hand-side vector 3987 3988 Output Parameter: 3989 . x - the result vector 3990 3991 Level: developer 3992 3993 Notes: 3994 `MatSolve()` should be used for most applications, as it performs 3995 a forward solve followed by a backward solve. 3996 3997 The vectors `b` and `x` cannot be the same. I.e., one cannot 3998 call `MatBackwardSolve`(A,x,x). 3999 4000 For matrix in `MATSEQBAIJ` format with block size larger than 1, 4001 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 4002 `MatForwardSolve()` solves $U^T*D y = b$, and 4003 `MatBackwardSolve()` solves $U x = y$. 4004 Thus they do not provide a symmetric preconditioner. 4005 4006 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 4007 @*/ 4008 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 4009 { 4010 PetscFunctionBegin; 4011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4012 PetscValidType(mat, 1); 4013 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4014 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4015 PetscCheckSameComm(mat, 1, b, 2); 4016 PetscCheckSameComm(mat, 1, x, 3); 4017 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4018 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); 4019 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); 4020 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); 4021 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4022 MatCheckPreallocated(mat, 1); 4023 4024 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 4025 PetscUseTypeMethod(mat, backwardsolve, b, x); 4026 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 4027 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4028 PetscFunctionReturn(PETSC_SUCCESS); 4029 } 4030 4031 /*@ 4032 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4033 4034 Neighbor-wise Collective 4035 4036 Input Parameters: 4037 + mat - the factored matrix 4038 . b - the right-hand-side vector 4039 - y - the vector to be added to 4040 4041 Output Parameter: 4042 . x - the result vector 4043 4044 Level: developer 4045 4046 Note: 4047 The vectors `b` and `x` cannot be the same. I.e., one cannot 4048 call `MatSolveAdd`(A,x,y,x). 4049 4050 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4051 @*/ 4052 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4053 { 4054 PetscScalar one = 1.0; 4055 Vec tmp; 4056 4057 PetscFunctionBegin; 4058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4059 PetscValidType(mat, 1); 4060 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4061 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4062 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4063 PetscCheckSameComm(mat, 1, b, 2); 4064 PetscCheckSameComm(mat, 1, y, 3); 4065 PetscCheckSameComm(mat, 1, x, 4); 4066 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4067 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); 4068 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); 4069 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); 4070 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); 4071 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); 4072 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4073 MatCheckPreallocated(mat, 1); 4074 4075 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4076 PetscCall(VecFlag(x, mat->factorerrortype)); 4077 if (mat->factorerrortype) { 4078 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4079 } else if (mat->ops->solveadd) { 4080 PetscUseTypeMethod(mat, solveadd, b, y, x); 4081 } else { 4082 /* do the solve then the add manually */ 4083 if (x != y) { 4084 PetscCall(MatSolve(mat, b, x)); 4085 PetscCall(VecAXPY(x, one, y)); 4086 } else { 4087 PetscCall(VecDuplicate(x, &tmp)); 4088 PetscCall(VecCopy(x, tmp)); 4089 PetscCall(MatSolve(mat, b, x)); 4090 PetscCall(VecAXPY(x, one, tmp)); 4091 PetscCall(VecDestroy(&tmp)); 4092 } 4093 } 4094 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4095 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4096 PetscFunctionReturn(PETSC_SUCCESS); 4097 } 4098 4099 /*@ 4100 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4101 4102 Neighbor-wise Collective 4103 4104 Input Parameters: 4105 + mat - the factored matrix 4106 - b - the right-hand-side vector 4107 4108 Output Parameter: 4109 . x - the result vector 4110 4111 Level: developer 4112 4113 Notes: 4114 The vectors `b` and `x` cannot be the same. I.e., one cannot 4115 call `MatSolveTranspose`(A,x,x). 4116 4117 Most users should employ the `KSP` interface for linear solvers 4118 instead of working directly with matrix algebra routines such as this. 4119 See, e.g., `KSPCreate()`. 4120 4121 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4122 @*/ 4123 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4124 { 4125 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4126 4127 PetscFunctionBegin; 4128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4129 PetscValidType(mat, 1); 4130 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4131 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4132 PetscCheckSameComm(mat, 1, b, 2); 4133 PetscCheckSameComm(mat, 1, x, 3); 4134 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4135 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); 4136 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); 4137 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4138 MatCheckPreallocated(mat, 1); 4139 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4140 PetscCall(VecFlag(x, mat->factorerrortype)); 4141 if (mat->factorerrortype) { 4142 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4143 } else { 4144 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4145 PetscCall((*f)(mat, b, x)); 4146 } 4147 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4148 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4149 PetscFunctionReturn(PETSC_SUCCESS); 4150 } 4151 4152 /*@ 4153 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4154 factored matrix. 4155 4156 Neighbor-wise Collective 4157 4158 Input Parameters: 4159 + mat - the factored matrix 4160 . b - the right-hand-side vector 4161 - y - the vector to be added to 4162 4163 Output Parameter: 4164 . x - the result vector 4165 4166 Level: developer 4167 4168 Note: 4169 The vectors `b` and `x` cannot be the same. I.e., one cannot 4170 call `MatSolveTransposeAdd`(A,x,y,x). 4171 4172 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4173 @*/ 4174 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4175 { 4176 PetscScalar one = 1.0; 4177 Vec tmp; 4178 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4179 4180 PetscFunctionBegin; 4181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4182 PetscValidType(mat, 1); 4183 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4184 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4185 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4186 PetscCheckSameComm(mat, 1, b, 2); 4187 PetscCheckSameComm(mat, 1, y, 3); 4188 PetscCheckSameComm(mat, 1, x, 4); 4189 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4190 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); 4191 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); 4192 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); 4193 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); 4194 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4195 MatCheckPreallocated(mat, 1); 4196 4197 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4198 PetscCall(VecFlag(x, mat->factorerrortype)); 4199 if (mat->factorerrortype) { 4200 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4201 } else if (f) { 4202 PetscCall((*f)(mat, b, y, x)); 4203 } else { 4204 /* do the solve then the add manually */ 4205 if (x != y) { 4206 PetscCall(MatSolveTranspose(mat, b, x)); 4207 PetscCall(VecAXPY(x, one, y)); 4208 } else { 4209 PetscCall(VecDuplicate(x, &tmp)); 4210 PetscCall(VecCopy(x, tmp)); 4211 PetscCall(MatSolveTranspose(mat, b, x)); 4212 PetscCall(VecAXPY(x, one, tmp)); 4213 PetscCall(VecDestroy(&tmp)); 4214 } 4215 } 4216 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4217 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4218 PetscFunctionReturn(PETSC_SUCCESS); 4219 } 4220 4221 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4222 /*@ 4223 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4224 4225 Neighbor-wise Collective 4226 4227 Input Parameters: 4228 + mat - the matrix 4229 . b - the right-hand side 4230 . omega - the relaxation factor 4231 . flag - flag indicating the type of SOR (see below) 4232 . shift - diagonal shift 4233 . its - the number of iterations 4234 - lits - the number of local iterations 4235 4236 Output Parameter: 4237 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4238 4239 SOR Flags: 4240 + `SOR_FORWARD_SWEEP` - forward SOR 4241 . `SOR_BACKWARD_SWEEP` - backward SOR 4242 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4243 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4244 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4245 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4246 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4247 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4248 upper/lower triangular part of matrix to 4249 vector (with omega) 4250 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4251 4252 Level: developer 4253 4254 Notes: 4255 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4256 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4257 on each processor. 4258 4259 Application programmers will not generally use `MatSOR()` directly, 4260 but instead will employ the `KSP`/`PC` interface. 4261 4262 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4263 4264 Most users should employ the `KSP` interface for linear solvers 4265 instead of working directly with matrix algebra routines such as this. 4266 See, e.g., `KSPCreate()`. 4267 4268 Vectors `x` and `b` CANNOT be the same 4269 4270 The flags are implemented as bitwise inclusive or operations. 4271 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4272 to specify a zero initial guess for SSOR. 4273 4274 Developer Note: 4275 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4276 4277 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4278 @*/ 4279 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4280 { 4281 PetscFunctionBegin; 4282 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4283 PetscValidType(mat, 1); 4284 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4285 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4286 PetscCheckSameComm(mat, 1, b, 2); 4287 PetscCheckSameComm(mat, 1, x, 8); 4288 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4289 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4290 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); 4291 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); 4292 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); 4293 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4294 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4295 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4296 4297 MatCheckPreallocated(mat, 1); 4298 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4299 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4300 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4301 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4302 PetscFunctionReturn(PETSC_SUCCESS); 4303 } 4304 4305 /* 4306 Default matrix copy routine. 4307 */ 4308 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4309 { 4310 PetscInt i, rstart = 0, rend = 0, nz; 4311 const PetscInt *cwork; 4312 const PetscScalar *vwork; 4313 4314 PetscFunctionBegin; 4315 if (B->assembled) PetscCall(MatZeroEntries(B)); 4316 if (str == SAME_NONZERO_PATTERN) { 4317 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4318 for (i = rstart; i < rend; i++) { 4319 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4320 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4321 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4322 } 4323 } else { 4324 PetscCall(MatAYPX(B, 0.0, A, str)); 4325 } 4326 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4327 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4328 PetscFunctionReturn(PETSC_SUCCESS); 4329 } 4330 4331 /*@ 4332 MatCopy - Copies a matrix to another matrix. 4333 4334 Collective 4335 4336 Input Parameters: 4337 + A - the matrix 4338 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4339 4340 Output Parameter: 4341 . B - where the copy is put 4342 4343 Level: intermediate 4344 4345 Notes: 4346 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4347 4348 `MatCopy()` copies the matrix entries of a matrix to another existing 4349 matrix (after first zeroing the second matrix). A related routine is 4350 `MatConvert()`, which first creates a new matrix and then copies the data. 4351 4352 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4353 @*/ 4354 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4355 { 4356 PetscInt i; 4357 4358 PetscFunctionBegin; 4359 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4360 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4361 PetscValidType(A, 1); 4362 PetscValidType(B, 2); 4363 PetscCheckSameComm(A, 1, B, 2); 4364 MatCheckPreallocated(B, 2); 4365 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4366 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4367 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, 4368 A->cmap->N, B->cmap->N); 4369 MatCheckPreallocated(A, 1); 4370 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4371 4372 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4373 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4374 else PetscCall(MatCopy_Basic(A, B, str)); 4375 4376 B->stencil.dim = A->stencil.dim; 4377 B->stencil.noc = A->stencil.noc; 4378 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4379 B->stencil.dims[i] = A->stencil.dims[i]; 4380 B->stencil.starts[i] = A->stencil.starts[i]; 4381 } 4382 4383 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4384 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4385 PetscFunctionReturn(PETSC_SUCCESS); 4386 } 4387 4388 /*@ 4389 MatConvert - Converts a matrix to another matrix, either of the same 4390 or different type. 4391 4392 Collective 4393 4394 Input Parameters: 4395 + mat - the matrix 4396 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4397 same type as the original matrix. 4398 - reuse - denotes if the destination matrix is to be created or reused. 4399 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 4400 `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). 4401 4402 Output Parameter: 4403 . M - pointer to place new matrix 4404 4405 Level: intermediate 4406 4407 Notes: 4408 `MatConvert()` first creates a new matrix and then copies the data from 4409 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4410 entries of one matrix to another already existing matrix context. 4411 4412 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4413 the MPI communicator of the generated matrix is always the same as the communicator 4414 of the input matrix. 4415 4416 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4417 @*/ 4418 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4419 { 4420 PetscBool sametype, issame, flg; 4421 PetscBool3 issymmetric, ishermitian; 4422 char convname[256], mtype[256]; 4423 Mat B; 4424 4425 PetscFunctionBegin; 4426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4427 PetscValidType(mat, 1); 4428 PetscAssertPointer(M, 4); 4429 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4430 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4431 MatCheckPreallocated(mat, 1); 4432 4433 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4434 if (flg) newtype = mtype; 4435 4436 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4437 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4438 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4439 if (reuse == MAT_REUSE_MATRIX) { 4440 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4441 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4442 } 4443 4444 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4445 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4446 PetscFunctionReturn(PETSC_SUCCESS); 4447 } 4448 4449 /* Cache Mat options because some converters use MatHeaderReplace */ 4450 issymmetric = mat->symmetric; 4451 ishermitian = mat->hermitian; 4452 4453 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4454 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4455 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4456 } else { 4457 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4458 const char *prefix[3] = {"seq", "mpi", ""}; 4459 PetscInt i; 4460 /* 4461 Order of precedence: 4462 0) See if newtype is a superclass of the current matrix. 4463 1) See if a specialized converter is known to the current matrix. 4464 2) See if a specialized converter is known to the desired matrix class. 4465 3) See if a good general converter is registered for the desired class 4466 (as of 6/27/03 only MATMPIADJ falls into this category). 4467 4) See if a good general converter is known for the current matrix. 4468 5) Use a really basic converter. 4469 */ 4470 4471 /* 0) See if newtype is a superclass of the current matrix. 4472 i.e mat is mpiaij and newtype is aij */ 4473 for (i = 0; i < 2; i++) { 4474 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4475 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4476 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4477 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4478 if (flg) { 4479 if (reuse == MAT_INPLACE_MATRIX) { 4480 PetscCall(PetscInfo(mat, "Early return\n")); 4481 PetscFunctionReturn(PETSC_SUCCESS); 4482 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4483 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4484 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4485 PetscFunctionReturn(PETSC_SUCCESS); 4486 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4487 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4488 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4489 PetscFunctionReturn(PETSC_SUCCESS); 4490 } 4491 } 4492 } 4493 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4494 for (i = 0; i < 3; i++) { 4495 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4496 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4497 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4498 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4499 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4500 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4501 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4502 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4503 if (conv) goto foundconv; 4504 } 4505 4506 /* 2) See if a specialized converter is known to the desired matrix class. */ 4507 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4508 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4509 PetscCall(MatSetType(B, newtype)); 4510 for (i = 0; i < 3; i++) { 4511 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4512 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4513 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4514 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4515 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4516 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4517 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4518 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4519 if (conv) { 4520 PetscCall(MatDestroy(&B)); 4521 goto foundconv; 4522 } 4523 } 4524 4525 /* 3) See if a good general converter is registered for the desired class */ 4526 conv = B->ops->convertfrom; 4527 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4528 PetscCall(MatDestroy(&B)); 4529 if (conv) goto foundconv; 4530 4531 /* 4) See if a good general converter is known for the current matrix */ 4532 if (mat->ops->convert) conv = mat->ops->convert; 4533 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4534 if (conv) goto foundconv; 4535 4536 /* 5) Use a really basic converter. */ 4537 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4538 conv = MatConvert_Basic; 4539 4540 foundconv: 4541 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4542 PetscCall((*conv)(mat, newtype, reuse, M)); 4543 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4544 /* the block sizes must be same if the mappings are copied over */ 4545 (*M)->rmap->bs = mat->rmap->bs; 4546 (*M)->cmap->bs = mat->cmap->bs; 4547 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4548 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4549 (*M)->rmap->mapping = mat->rmap->mapping; 4550 (*M)->cmap->mapping = mat->cmap->mapping; 4551 } 4552 (*M)->stencil.dim = mat->stencil.dim; 4553 (*M)->stencil.noc = mat->stencil.noc; 4554 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4555 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4556 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4557 } 4558 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4559 } 4560 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4561 4562 /* Copy Mat options */ 4563 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4564 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4565 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4566 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4567 PetscFunctionReturn(PETSC_SUCCESS); 4568 } 4569 4570 /*@ 4571 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4572 4573 Not Collective 4574 4575 Input Parameter: 4576 . mat - the matrix, must be a factored matrix 4577 4578 Output Parameter: 4579 . type - the string name of the package (do not free this string) 4580 4581 Level: intermediate 4582 4583 Fortran Note: 4584 Pass in an empty string that is long enough and the package name will be copied into it. 4585 4586 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4587 @*/ 4588 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4589 { 4590 PetscErrorCode (*conv)(Mat, MatSolverType *); 4591 4592 PetscFunctionBegin; 4593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4594 PetscValidType(mat, 1); 4595 PetscAssertPointer(type, 2); 4596 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4597 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4598 if (conv) PetscCall((*conv)(mat, type)); 4599 else *type = MATSOLVERPETSC; 4600 PetscFunctionReturn(PETSC_SUCCESS); 4601 } 4602 4603 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4604 struct _MatSolverTypeForSpecifcType { 4605 MatType mtype; 4606 /* no entry for MAT_FACTOR_NONE */ 4607 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4608 MatSolverTypeForSpecifcType next; 4609 }; 4610 4611 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4612 struct _MatSolverTypeHolder { 4613 char *name; 4614 MatSolverTypeForSpecifcType handlers; 4615 MatSolverTypeHolder next; 4616 }; 4617 4618 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4619 4620 /*@C 4621 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4622 4623 Logically Collective, No Fortran Support 4624 4625 Input Parameters: 4626 + package - name of the package, for example petsc or superlu 4627 . mtype - the matrix type that works with this package 4628 . ftype - the type of factorization supported by the package 4629 - createfactor - routine that will create the factored matrix ready to be used 4630 4631 Level: developer 4632 4633 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4634 `MatGetFactor()` 4635 @*/ 4636 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4637 { 4638 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4639 PetscBool flg; 4640 MatSolverTypeForSpecifcType inext, iprev = NULL; 4641 4642 PetscFunctionBegin; 4643 PetscCall(MatInitializePackage()); 4644 if (!next) { 4645 PetscCall(PetscNew(&MatSolverTypeHolders)); 4646 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4647 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4648 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4649 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4650 PetscFunctionReturn(PETSC_SUCCESS); 4651 } 4652 while (next) { 4653 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4654 if (flg) { 4655 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4656 inext = next->handlers; 4657 while (inext) { 4658 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4659 if (flg) { 4660 inext->createfactor[(int)ftype - 1] = createfactor; 4661 PetscFunctionReturn(PETSC_SUCCESS); 4662 } 4663 iprev = inext; 4664 inext = inext->next; 4665 } 4666 PetscCall(PetscNew(&iprev->next)); 4667 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4668 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4669 PetscFunctionReturn(PETSC_SUCCESS); 4670 } 4671 prev = next; 4672 next = next->next; 4673 } 4674 PetscCall(PetscNew(&prev->next)); 4675 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4676 PetscCall(PetscNew(&prev->next->handlers)); 4677 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4678 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4679 PetscFunctionReturn(PETSC_SUCCESS); 4680 } 4681 4682 /*@C 4683 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4684 4685 Input Parameters: 4686 + 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 4687 . ftype - the type of factorization supported by the type 4688 - mtype - the matrix type that works with this type 4689 4690 Output Parameters: 4691 + foundtype - `PETSC_TRUE` if the type was registered 4692 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4693 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4694 4695 Calling sequence of `createfactor`: 4696 + A - the matrix providing the factor matrix 4697 . ftype - the `MatFactorType` of the factor requested 4698 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4699 4700 Level: developer 4701 4702 Note: 4703 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4704 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4705 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4706 4707 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4708 `MatInitializePackage()` 4709 @*/ 4710 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4711 { 4712 MatSolverTypeHolder next = MatSolverTypeHolders; 4713 PetscBool flg; 4714 MatSolverTypeForSpecifcType inext; 4715 4716 PetscFunctionBegin; 4717 if (foundtype) *foundtype = PETSC_FALSE; 4718 if (foundmtype) *foundmtype = PETSC_FALSE; 4719 if (createfactor) *createfactor = NULL; 4720 4721 if (type) { 4722 while (next) { 4723 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4724 if (flg) { 4725 if (foundtype) *foundtype = PETSC_TRUE; 4726 inext = next->handlers; 4727 while (inext) { 4728 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4729 if (flg) { 4730 if (foundmtype) *foundmtype = PETSC_TRUE; 4731 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4732 PetscFunctionReturn(PETSC_SUCCESS); 4733 } 4734 inext = inext->next; 4735 } 4736 } 4737 next = next->next; 4738 } 4739 } else { 4740 while (next) { 4741 inext = next->handlers; 4742 while (inext) { 4743 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4744 if (flg && inext->createfactor[(int)ftype - 1]) { 4745 if (foundtype) *foundtype = PETSC_TRUE; 4746 if (foundmtype) *foundmtype = PETSC_TRUE; 4747 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4748 PetscFunctionReturn(PETSC_SUCCESS); 4749 } 4750 inext = inext->next; 4751 } 4752 next = next->next; 4753 } 4754 /* try with base classes inext->mtype */ 4755 next = MatSolverTypeHolders; 4756 while (next) { 4757 inext = next->handlers; 4758 while (inext) { 4759 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4760 if (flg && inext->createfactor[(int)ftype - 1]) { 4761 if (foundtype) *foundtype = PETSC_TRUE; 4762 if (foundmtype) *foundmtype = PETSC_TRUE; 4763 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4764 PetscFunctionReturn(PETSC_SUCCESS); 4765 } 4766 inext = inext->next; 4767 } 4768 next = next->next; 4769 } 4770 } 4771 PetscFunctionReturn(PETSC_SUCCESS); 4772 } 4773 4774 PetscErrorCode MatSolverTypeDestroy(void) 4775 { 4776 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4777 MatSolverTypeForSpecifcType inext, iprev; 4778 4779 PetscFunctionBegin; 4780 while (next) { 4781 PetscCall(PetscFree(next->name)); 4782 inext = next->handlers; 4783 while (inext) { 4784 PetscCall(PetscFree(inext->mtype)); 4785 iprev = inext; 4786 inext = inext->next; 4787 PetscCall(PetscFree(iprev)); 4788 } 4789 prev = next; 4790 next = next->next; 4791 PetscCall(PetscFree(prev)); 4792 } 4793 MatSolverTypeHolders = NULL; 4794 PetscFunctionReturn(PETSC_SUCCESS); 4795 } 4796 4797 /*@ 4798 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4799 4800 Logically Collective 4801 4802 Input Parameter: 4803 . mat - the matrix 4804 4805 Output Parameter: 4806 . flg - `PETSC_TRUE` if uses the ordering 4807 4808 Level: developer 4809 4810 Note: 4811 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4812 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4813 4814 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4815 @*/ 4816 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4817 { 4818 PetscFunctionBegin; 4819 *flg = mat->canuseordering; 4820 PetscFunctionReturn(PETSC_SUCCESS); 4821 } 4822 4823 /*@ 4824 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4825 4826 Logically Collective 4827 4828 Input Parameters: 4829 + mat - the matrix obtained with `MatGetFactor()` 4830 - ftype - the factorization type to be used 4831 4832 Output Parameter: 4833 . otype - the preferred ordering type 4834 4835 Level: developer 4836 4837 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4838 @*/ 4839 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4840 { 4841 PetscFunctionBegin; 4842 *otype = mat->preferredordering[ftype]; 4843 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4844 PetscFunctionReturn(PETSC_SUCCESS); 4845 } 4846 4847 /*@ 4848 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4849 4850 Collective 4851 4852 Input Parameters: 4853 + mat - the matrix 4854 . 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 4855 the other criteria is returned 4856 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4857 4858 Output Parameter: 4859 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4860 4861 Options Database Keys: 4862 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4863 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4864 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4865 4866 Level: intermediate 4867 4868 Notes: 4869 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4870 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4871 4872 Users usually access the factorization solvers via `KSP` 4873 4874 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4875 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 4876 4877 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4878 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4879 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4880 4881 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4882 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4883 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4884 4885 Developer Note: 4886 This should actually be called `MatCreateFactor()` since it creates a new factor object 4887 4888 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4889 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4890 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4891 @*/ 4892 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4893 { 4894 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4895 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4896 4897 PetscFunctionBegin; 4898 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4899 PetscValidType(mat, 1); 4900 4901 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4902 MatCheckPreallocated(mat, 1); 4903 4904 PetscCall(MatIsShell(mat, &shell)); 4905 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4906 if (hasop) { 4907 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4908 PetscFunctionReturn(PETSC_SUCCESS); 4909 } 4910 4911 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4912 if (!foundtype) { 4913 if (type) { 4914 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], 4915 ((PetscObject)mat)->type_name, type); 4916 } else { 4917 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); 4918 } 4919 } 4920 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4921 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); 4922 4923 PetscCall((*conv)(mat, ftype, f)); 4924 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4925 PetscFunctionReturn(PETSC_SUCCESS); 4926 } 4927 4928 /*@ 4929 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4930 4931 Not Collective 4932 4933 Input Parameters: 4934 + mat - the matrix 4935 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4936 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4937 4938 Output Parameter: 4939 . flg - PETSC_TRUE if the factorization is available 4940 4941 Level: intermediate 4942 4943 Notes: 4944 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4945 such as pastix, superlu, mumps etc. 4946 4947 PETSc must have been ./configure to use the external solver, using the option --download-package 4948 4949 Developer Note: 4950 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4951 4952 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4953 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4954 @*/ 4955 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4956 { 4957 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4958 4959 PetscFunctionBegin; 4960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4961 PetscAssertPointer(flg, 4); 4962 4963 *flg = PETSC_FALSE; 4964 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4965 4966 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4967 MatCheckPreallocated(mat, 1); 4968 4969 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4970 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4971 PetscFunctionReturn(PETSC_SUCCESS); 4972 } 4973 4974 /*@ 4975 MatDuplicate - Duplicates a matrix including the non-zero structure. 4976 4977 Collective 4978 4979 Input Parameters: 4980 + mat - the matrix 4981 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4982 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4983 4984 Output Parameter: 4985 . M - pointer to place new matrix 4986 4987 Level: intermediate 4988 4989 Notes: 4990 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4991 4992 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4993 4994 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. 4995 4996 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4997 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4998 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4999 5000 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 5001 @*/ 5002 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 5003 { 5004 Mat B; 5005 VecType vtype; 5006 PetscInt i; 5007 PetscObject dm, container_h, container_d; 5008 void (*viewf)(void); 5009 5010 PetscFunctionBegin; 5011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5012 PetscValidType(mat, 1); 5013 PetscAssertPointer(M, 3); 5014 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 5015 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5016 MatCheckPreallocated(mat, 1); 5017 5018 *M = NULL; 5019 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 5020 PetscUseTypeMethod(mat, duplicate, op, M); 5021 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 5022 B = *M; 5023 5024 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 5025 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 5026 PetscCall(MatGetVecType(mat, &vtype)); 5027 PetscCall(MatSetVecType(B, vtype)); 5028 5029 B->stencil.dim = mat->stencil.dim; 5030 B->stencil.noc = mat->stencil.noc; 5031 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 5032 B->stencil.dims[i] = mat->stencil.dims[i]; 5033 B->stencil.starts[i] = mat->stencil.starts[i]; 5034 } 5035 5036 B->nooffproczerorows = mat->nooffproczerorows; 5037 B->nooffprocentries = mat->nooffprocentries; 5038 5039 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5040 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5041 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5042 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5043 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5044 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5045 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5046 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5047 PetscFunctionReturn(PETSC_SUCCESS); 5048 } 5049 5050 /*@ 5051 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5052 5053 Logically Collective 5054 5055 Input Parameter: 5056 . mat - the matrix 5057 5058 Output Parameter: 5059 . v - the diagonal of the matrix 5060 5061 Level: intermediate 5062 5063 Note: 5064 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5065 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5066 is larger than `ndiag`, the values of the remaining entries are unspecified. 5067 5068 Currently only correct in parallel for square matrices. 5069 5070 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5071 @*/ 5072 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5073 { 5074 PetscFunctionBegin; 5075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5076 PetscValidType(mat, 1); 5077 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5078 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5079 MatCheckPreallocated(mat, 1); 5080 if (PetscDefined(USE_DEBUG)) { 5081 PetscInt nv, row, col, ndiag; 5082 5083 PetscCall(VecGetLocalSize(v, &nv)); 5084 PetscCall(MatGetLocalSize(mat, &row, &col)); 5085 ndiag = PetscMin(row, col); 5086 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); 5087 } 5088 5089 PetscUseTypeMethod(mat, getdiagonal, v); 5090 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5091 PetscFunctionReturn(PETSC_SUCCESS); 5092 } 5093 5094 /*@ 5095 MatGetRowMin - Gets the minimum value (of the real part) of each 5096 row of the matrix 5097 5098 Logically Collective 5099 5100 Input Parameter: 5101 . mat - the matrix 5102 5103 Output Parameters: 5104 + v - the vector for storing the maximums 5105 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5106 5107 Level: intermediate 5108 5109 Note: 5110 The result of this call are the same as if one converted the matrix to dense format 5111 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5112 5113 This code is only implemented for a couple of matrix formats. 5114 5115 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5116 `MatGetRowMax()` 5117 @*/ 5118 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5119 { 5120 PetscFunctionBegin; 5121 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5122 PetscValidType(mat, 1); 5123 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5124 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5125 5126 if (!mat->cmap->N) { 5127 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5128 if (idx) { 5129 PetscInt i, m = mat->rmap->n; 5130 for (i = 0; i < m; i++) idx[i] = -1; 5131 } 5132 } else { 5133 MatCheckPreallocated(mat, 1); 5134 } 5135 PetscUseTypeMethod(mat, getrowmin, v, idx); 5136 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5137 PetscFunctionReturn(PETSC_SUCCESS); 5138 } 5139 5140 /*@ 5141 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5142 row of the matrix 5143 5144 Logically Collective 5145 5146 Input Parameter: 5147 . mat - the matrix 5148 5149 Output Parameters: 5150 + v - the vector for storing the minimums 5151 - idx - the indices of the column found for each row (or `NULL` if not needed) 5152 5153 Level: intermediate 5154 5155 Notes: 5156 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5157 row is 0 (the first column). 5158 5159 This code is only implemented for a couple of matrix formats. 5160 5161 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5162 @*/ 5163 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5164 { 5165 PetscFunctionBegin; 5166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5167 PetscValidType(mat, 1); 5168 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5169 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5170 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5171 5172 if (!mat->cmap->N) { 5173 PetscCall(VecSet(v, 0.0)); 5174 if (idx) { 5175 PetscInt i, m = mat->rmap->n; 5176 for (i = 0; i < m; i++) idx[i] = -1; 5177 } 5178 } else { 5179 MatCheckPreallocated(mat, 1); 5180 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5181 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5182 } 5183 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5184 PetscFunctionReturn(PETSC_SUCCESS); 5185 } 5186 5187 /*@ 5188 MatGetRowMax - Gets the maximum value (of the real part) of each 5189 row of the matrix 5190 5191 Logically Collective 5192 5193 Input Parameter: 5194 . mat - the matrix 5195 5196 Output Parameters: 5197 + v - the vector for storing the maximums 5198 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5199 5200 Level: intermediate 5201 5202 Notes: 5203 The result of this call are the same as if one converted the matrix to dense format 5204 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5205 5206 This code is only implemented for a couple of matrix formats. 5207 5208 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5209 @*/ 5210 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5211 { 5212 PetscFunctionBegin; 5213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5214 PetscValidType(mat, 1); 5215 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5216 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5217 5218 if (!mat->cmap->N) { 5219 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5220 if (idx) { 5221 PetscInt i, m = mat->rmap->n; 5222 for (i = 0; i < m; i++) idx[i] = -1; 5223 } 5224 } else { 5225 MatCheckPreallocated(mat, 1); 5226 PetscUseTypeMethod(mat, getrowmax, v, idx); 5227 } 5228 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5229 PetscFunctionReturn(PETSC_SUCCESS); 5230 } 5231 5232 /*@ 5233 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5234 row of the matrix 5235 5236 Logically Collective 5237 5238 Input Parameter: 5239 . mat - the matrix 5240 5241 Output Parameters: 5242 + v - the vector for storing the maximums 5243 - idx - the indices of the column found for each row (or `NULL` if not needed) 5244 5245 Level: intermediate 5246 5247 Notes: 5248 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5249 row is 0 (the first column). 5250 5251 This code is only implemented for a couple of matrix formats. 5252 5253 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5254 @*/ 5255 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5256 { 5257 PetscFunctionBegin; 5258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5259 PetscValidType(mat, 1); 5260 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5262 5263 if (!mat->cmap->N) { 5264 PetscCall(VecSet(v, 0.0)); 5265 if (idx) { 5266 PetscInt i, m = mat->rmap->n; 5267 for (i = 0; i < m; i++) idx[i] = -1; 5268 } 5269 } else { 5270 MatCheckPreallocated(mat, 1); 5271 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5272 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5273 } 5274 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5275 PetscFunctionReturn(PETSC_SUCCESS); 5276 } 5277 5278 /*@ 5279 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5280 5281 Logically Collective 5282 5283 Input Parameter: 5284 . mat - the matrix 5285 5286 Output Parameter: 5287 . v - the vector for storing the sum 5288 5289 Level: intermediate 5290 5291 This code is only implemented for a couple of matrix formats. 5292 5293 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5294 @*/ 5295 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5296 { 5297 PetscFunctionBegin; 5298 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5299 PetscValidType(mat, 1); 5300 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5302 5303 if (!mat->cmap->N) { 5304 PetscCall(VecSet(v, 0.0)); 5305 } else { 5306 MatCheckPreallocated(mat, 1); 5307 PetscUseTypeMethod(mat, getrowsumabs, v); 5308 } 5309 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5310 PetscFunctionReturn(PETSC_SUCCESS); 5311 } 5312 5313 /*@ 5314 MatGetRowSum - Gets the sum of each row of the matrix 5315 5316 Logically or Neighborhood Collective 5317 5318 Input Parameter: 5319 . mat - the matrix 5320 5321 Output Parameter: 5322 . v - the vector for storing the sum of rows 5323 5324 Level: intermediate 5325 5326 Note: 5327 This code is slow since it is not currently specialized for different formats 5328 5329 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5330 @*/ 5331 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5332 { 5333 Vec ones; 5334 5335 PetscFunctionBegin; 5336 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5337 PetscValidType(mat, 1); 5338 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5339 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5340 MatCheckPreallocated(mat, 1); 5341 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5342 PetscCall(VecSet(ones, 1.)); 5343 PetscCall(MatMult(mat, ones, v)); 5344 PetscCall(VecDestroy(&ones)); 5345 PetscFunctionReturn(PETSC_SUCCESS); 5346 } 5347 5348 /*@ 5349 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5350 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5351 5352 Collective 5353 5354 Input Parameter: 5355 . mat - the matrix to provide the transpose 5356 5357 Output Parameter: 5358 . 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 5359 5360 Level: advanced 5361 5362 Note: 5363 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 5364 routine allows bypassing that call. 5365 5366 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5367 @*/ 5368 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5369 { 5370 MatParentState *rb = NULL; 5371 5372 PetscFunctionBegin; 5373 PetscCall(PetscNew(&rb)); 5374 rb->id = ((PetscObject)mat)->id; 5375 rb->state = 0; 5376 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5377 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5378 PetscFunctionReturn(PETSC_SUCCESS); 5379 } 5380 5381 /*@ 5382 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5383 5384 Collective 5385 5386 Input Parameters: 5387 + mat - the matrix to transpose 5388 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5389 5390 Output Parameter: 5391 . B - the transpose of the matrix 5392 5393 Level: intermediate 5394 5395 Notes: 5396 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5397 5398 `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 5399 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5400 5401 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. 5402 5403 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5404 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5405 5406 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5407 5408 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5409 5410 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5411 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5412 @*/ 5413 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5414 { 5415 PetscContainer rB = NULL; 5416 MatParentState *rb = NULL; 5417 5418 PetscFunctionBegin; 5419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5420 PetscValidType(mat, 1); 5421 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5422 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5423 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5424 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5425 MatCheckPreallocated(mat, 1); 5426 if (reuse == MAT_REUSE_MATRIX) { 5427 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5428 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5429 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5430 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5431 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5432 } 5433 5434 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5435 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5436 PetscUseTypeMethod(mat, transpose, reuse, B); 5437 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5438 } 5439 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5440 5441 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5442 if (reuse != MAT_INPLACE_MATRIX) { 5443 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5444 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5445 rb->state = ((PetscObject)mat)->state; 5446 rb->nonzerostate = mat->nonzerostate; 5447 } 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 /*@ 5452 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5453 5454 Collective 5455 5456 Input Parameter: 5457 . A - the matrix to transpose 5458 5459 Output Parameter: 5460 . 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 5461 numerical portion. 5462 5463 Level: intermediate 5464 5465 Note: 5466 This is not supported for many matrix types, use `MatTranspose()` in those cases 5467 5468 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5469 @*/ 5470 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5471 { 5472 PetscFunctionBegin; 5473 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5474 PetscValidType(A, 1); 5475 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5476 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5477 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5478 PetscUseTypeMethod(A, transposesymbolic, B); 5479 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5480 5481 PetscCall(MatTransposeSetPrecursor(A, *B)); 5482 PetscFunctionReturn(PETSC_SUCCESS); 5483 } 5484 5485 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5486 { 5487 PetscContainer rB; 5488 MatParentState *rb; 5489 5490 PetscFunctionBegin; 5491 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5492 PetscValidType(A, 1); 5493 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5494 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5495 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5496 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5497 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5498 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5499 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5500 PetscFunctionReturn(PETSC_SUCCESS); 5501 } 5502 5503 /*@ 5504 MatIsTranspose - Test whether a matrix is another one's transpose, 5505 or its own, in which case it tests symmetry. 5506 5507 Collective 5508 5509 Input Parameters: 5510 + A - the matrix to test 5511 . B - the matrix to test against, this can equal the first parameter 5512 - tol - tolerance, differences between entries smaller than this are counted as zero 5513 5514 Output Parameter: 5515 . flg - the result 5516 5517 Level: intermediate 5518 5519 Notes: 5520 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5521 test involves parallel copies of the block off-diagonal parts of the matrix. 5522 5523 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5524 @*/ 5525 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5526 { 5527 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5528 5529 PetscFunctionBegin; 5530 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5531 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5532 PetscAssertPointer(flg, 4); 5533 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5534 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5535 *flg = PETSC_FALSE; 5536 if (f && g) { 5537 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5538 PetscCall((*f)(A, B, tol, flg)); 5539 } else { 5540 MatType mattype; 5541 5542 PetscCall(MatGetType(f ? B : A, &mattype)); 5543 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5544 } 5545 PetscFunctionReturn(PETSC_SUCCESS); 5546 } 5547 5548 /*@ 5549 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5550 5551 Collective 5552 5553 Input Parameters: 5554 + mat - the matrix to transpose and complex conjugate 5555 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5556 5557 Output Parameter: 5558 . B - the Hermitian transpose 5559 5560 Level: intermediate 5561 5562 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5563 @*/ 5564 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5565 { 5566 PetscFunctionBegin; 5567 PetscCall(MatTranspose(mat, reuse, B)); 5568 #if defined(PETSC_USE_COMPLEX) 5569 PetscCall(MatConjugate(*B)); 5570 #endif 5571 PetscFunctionReturn(PETSC_SUCCESS); 5572 } 5573 5574 /*@ 5575 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5576 5577 Collective 5578 5579 Input Parameters: 5580 + A - the matrix to test 5581 . B - the matrix to test against, this can equal the first parameter 5582 - tol - tolerance, differences between entries smaller than this are counted as zero 5583 5584 Output Parameter: 5585 . flg - the result 5586 5587 Level: intermediate 5588 5589 Notes: 5590 Only available for `MATAIJ` matrices. 5591 5592 The sequential algorithm 5593 has a running time of the order of the number of nonzeros; the parallel 5594 test involves parallel copies of the block off-diagonal parts of the matrix. 5595 5596 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5597 @*/ 5598 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5599 { 5600 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5601 5602 PetscFunctionBegin; 5603 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5604 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5605 PetscAssertPointer(flg, 4); 5606 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5607 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5608 if (f && g) { 5609 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5610 PetscCall((*f)(A, B, tol, flg)); 5611 } 5612 PetscFunctionReturn(PETSC_SUCCESS); 5613 } 5614 5615 /*@ 5616 MatPermute - Creates a new matrix with rows and columns permuted from the 5617 original. 5618 5619 Collective 5620 5621 Input Parameters: 5622 + mat - the matrix to permute 5623 . row - row permutation, each processor supplies only the permutation for its rows 5624 - col - column permutation, each processor supplies only the permutation for its columns 5625 5626 Output Parameter: 5627 . B - the permuted matrix 5628 5629 Level: advanced 5630 5631 Note: 5632 The index sets map from row/col of permuted matrix to row/col of original matrix. 5633 The index sets should be on the same communicator as mat and have the same local sizes. 5634 5635 Developer Note: 5636 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5637 exploit the fact that row and col are permutations, consider implementing the 5638 more general `MatCreateSubMatrix()` instead. 5639 5640 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5641 @*/ 5642 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5643 { 5644 PetscFunctionBegin; 5645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5646 PetscValidType(mat, 1); 5647 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5648 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5649 PetscAssertPointer(B, 4); 5650 PetscCheckSameComm(mat, 1, row, 2); 5651 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5652 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5653 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5654 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5655 MatCheckPreallocated(mat, 1); 5656 5657 if (mat->ops->permute) { 5658 PetscUseTypeMethod(mat, permute, row, col, B); 5659 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5660 } else { 5661 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5662 } 5663 PetscFunctionReturn(PETSC_SUCCESS); 5664 } 5665 5666 /*@ 5667 MatEqual - Compares two matrices. 5668 5669 Collective 5670 5671 Input Parameters: 5672 + A - the first matrix 5673 - B - the second matrix 5674 5675 Output Parameter: 5676 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5677 5678 Level: intermediate 5679 5680 Note: 5681 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product 5682 using several randomly created vectors, see `MatMultEqual()`. 5683 5684 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5685 @*/ 5686 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5687 { 5688 PetscFunctionBegin; 5689 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5690 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5691 PetscValidType(A, 1); 5692 PetscValidType(B, 2); 5693 PetscAssertPointer(flg, 3); 5694 PetscCheckSameComm(A, 1, B, 2); 5695 MatCheckPreallocated(A, 1); 5696 MatCheckPreallocated(B, 2); 5697 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5698 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5699 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, 5700 B->cmap->N); 5701 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5702 PetscUseTypeMethod(A, equal, B, flg); 5703 } else { 5704 PetscCall(MatMultEqual(A, B, 10, flg)); 5705 } 5706 PetscFunctionReturn(PETSC_SUCCESS); 5707 } 5708 5709 /*@ 5710 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5711 matrices that are stored as vectors. Either of the two scaling 5712 matrices can be `NULL`. 5713 5714 Collective 5715 5716 Input Parameters: 5717 + mat - the matrix to be scaled 5718 . l - the left scaling vector (or `NULL`) 5719 - r - the right scaling vector (or `NULL`) 5720 5721 Level: intermediate 5722 5723 Note: 5724 `MatDiagonalScale()` computes $A = LAR$, where 5725 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5726 The L scales the rows of the matrix, the R scales the columns of the matrix. 5727 5728 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5729 @*/ 5730 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5731 { 5732 PetscFunctionBegin; 5733 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5734 PetscValidType(mat, 1); 5735 if (l) { 5736 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5737 PetscCheckSameComm(mat, 1, l, 2); 5738 } 5739 if (r) { 5740 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5741 PetscCheckSameComm(mat, 1, r, 3); 5742 } 5743 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5744 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5745 MatCheckPreallocated(mat, 1); 5746 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5747 5748 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5749 PetscUseTypeMethod(mat, diagonalscale, l, r); 5750 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5751 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5752 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5753 PetscFunctionReturn(PETSC_SUCCESS); 5754 } 5755 5756 /*@ 5757 MatScale - Scales all elements of a matrix by a given number. 5758 5759 Logically Collective 5760 5761 Input Parameters: 5762 + mat - the matrix to be scaled 5763 - a - the scaling value 5764 5765 Level: intermediate 5766 5767 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5768 @*/ 5769 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5770 { 5771 PetscFunctionBegin; 5772 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5773 PetscValidType(mat, 1); 5774 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5775 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5776 PetscValidLogicalCollectiveScalar(mat, a, 2); 5777 MatCheckPreallocated(mat, 1); 5778 5779 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5780 if (a != (PetscScalar)1.0) { 5781 PetscUseTypeMethod(mat, scale, a); 5782 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5783 } 5784 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5785 PetscFunctionReturn(PETSC_SUCCESS); 5786 } 5787 5788 /*@ 5789 MatNorm - Calculates various norms of a matrix. 5790 5791 Collective 5792 5793 Input Parameters: 5794 + mat - the matrix 5795 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5796 5797 Output Parameter: 5798 . nrm - the resulting norm 5799 5800 Level: intermediate 5801 5802 .seealso: [](ch_matrices), `Mat` 5803 @*/ 5804 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5805 { 5806 PetscFunctionBegin; 5807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5808 PetscValidType(mat, 1); 5809 PetscAssertPointer(nrm, 3); 5810 5811 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5812 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5813 MatCheckPreallocated(mat, 1); 5814 5815 PetscUseTypeMethod(mat, norm, type, nrm); 5816 PetscFunctionReturn(PETSC_SUCCESS); 5817 } 5818 5819 /* 5820 This variable is used to prevent counting of MatAssemblyBegin() that 5821 are called from within a MatAssemblyEnd(). 5822 */ 5823 static PetscInt MatAssemblyEnd_InUse = 0; 5824 /*@ 5825 MatAssemblyBegin - Begins assembling the matrix. This routine should 5826 be called after completing all calls to `MatSetValues()`. 5827 5828 Collective 5829 5830 Input Parameters: 5831 + mat - the matrix 5832 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5833 5834 Level: beginner 5835 5836 Notes: 5837 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5838 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5839 5840 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5841 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5842 using the matrix. 5843 5844 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5845 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 5846 a global collective operation requiring all processes that share the matrix. 5847 5848 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5849 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5850 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5851 5852 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5853 @*/ 5854 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5855 { 5856 PetscFunctionBegin; 5857 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5858 PetscValidType(mat, 1); 5859 MatCheckPreallocated(mat, 1); 5860 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5861 if (mat->assembled) { 5862 mat->was_assembled = PETSC_TRUE; 5863 mat->assembled = PETSC_FALSE; 5864 } 5865 5866 if (!MatAssemblyEnd_InUse) { 5867 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5868 PetscTryTypeMethod(mat, assemblybegin, type); 5869 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5870 } else PetscTryTypeMethod(mat, assemblybegin, type); 5871 PetscFunctionReturn(PETSC_SUCCESS); 5872 } 5873 5874 /*@ 5875 MatAssembled - Indicates if a matrix has been assembled and is ready for 5876 use; for example, in matrix-vector product. 5877 5878 Not Collective 5879 5880 Input Parameter: 5881 . mat - the matrix 5882 5883 Output Parameter: 5884 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5885 5886 Level: advanced 5887 5888 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5889 @*/ 5890 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5891 { 5892 PetscFunctionBegin; 5893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5894 PetscAssertPointer(assembled, 2); 5895 *assembled = mat->assembled; 5896 PetscFunctionReturn(PETSC_SUCCESS); 5897 } 5898 5899 /*@ 5900 MatAssemblyEnd - Completes assembling the matrix. This routine should 5901 be called after `MatAssemblyBegin()`. 5902 5903 Collective 5904 5905 Input Parameters: 5906 + mat - the matrix 5907 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5908 5909 Options Database Keys: 5910 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5911 . -mat_view ::ascii_info_detail - Prints more detailed info 5912 . -mat_view - Prints matrix in ASCII format 5913 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5914 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5915 . -display <name> - Sets display name (default is host) 5916 . -draw_pause <sec> - Sets number of seconds to pause after display 5917 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5918 . -viewer_socket_machine <machine> - Machine to use for socket 5919 . -viewer_socket_port <port> - Port number to use for socket 5920 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5921 5922 Level: beginner 5923 5924 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5925 @*/ 5926 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5927 { 5928 static PetscInt inassm = 0; 5929 PetscBool flg = PETSC_FALSE; 5930 5931 PetscFunctionBegin; 5932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5933 PetscValidType(mat, 1); 5934 5935 inassm++; 5936 MatAssemblyEnd_InUse++; 5937 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5938 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5939 PetscTryTypeMethod(mat, assemblyend, type); 5940 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5941 } else PetscTryTypeMethod(mat, assemblyend, type); 5942 5943 /* Flush assembly is not a true assembly */ 5944 if (type != MAT_FLUSH_ASSEMBLY) { 5945 if (mat->num_ass) { 5946 if (!mat->symmetry_eternal) { 5947 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5948 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5949 } 5950 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5951 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5952 } 5953 mat->num_ass++; 5954 mat->assembled = PETSC_TRUE; 5955 mat->ass_nonzerostate = mat->nonzerostate; 5956 } 5957 5958 mat->insertmode = NOT_SET_VALUES; 5959 MatAssemblyEnd_InUse--; 5960 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5961 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5962 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5963 5964 if (mat->checksymmetryonassembly) { 5965 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5966 if (flg) { 5967 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5968 } else { 5969 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5970 } 5971 } 5972 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5973 } 5974 inassm--; 5975 PetscFunctionReturn(PETSC_SUCCESS); 5976 } 5977 5978 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5979 /*@ 5980 MatSetOption - Sets a parameter option for a matrix. Some options 5981 may be specific to certain storage formats. Some options 5982 determine how values will be inserted (or added). Sorted, 5983 row-oriented input will generally assemble the fastest. The default 5984 is row-oriented. 5985 5986 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5987 5988 Input Parameters: 5989 + mat - the matrix 5990 . op - the option, one of those listed below (and possibly others), 5991 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5992 5993 Options Describing Matrix Structure: 5994 + `MAT_SPD` - symmetric positive definite 5995 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5996 . `MAT_HERMITIAN` - transpose is the complex conjugation 5997 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5998 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5999 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 6000 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 6001 6002 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 6003 do not need to be computed (usually at a high cost) 6004 6005 Options For Use with `MatSetValues()`: 6006 Insert a logically dense subblock, which can be 6007 . `MAT_ROW_ORIENTED` - row-oriented (default) 6008 6009 These options reflect the data you pass in with `MatSetValues()`; it has 6010 nothing to do with how the data is stored internally in the matrix 6011 data structure. 6012 6013 When (re)assembling a matrix, we can restrict the input for 6014 efficiency/debugging purposes. These options include 6015 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 6016 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 6017 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 6018 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 6019 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 6020 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 6021 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 6022 performance for very large process counts. 6023 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 6024 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 6025 functions, instead sending only neighbor messages. 6026 6027 Level: intermediate 6028 6029 Notes: 6030 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 6031 6032 Some options are relevant only for particular matrix types and 6033 are thus ignored by others. Other options are not supported by 6034 certain matrix types and will generate an error message if set. 6035 6036 If using Fortran to compute a matrix, one may need to 6037 use the column-oriented option (or convert to the row-oriented 6038 format). 6039 6040 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6041 that would generate a new entry in the nonzero structure is instead 6042 ignored. Thus, if memory has not already been allocated for this particular 6043 data, then the insertion is ignored. For dense matrices, in which 6044 the entire array is allocated, no entries are ever ignored. 6045 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6046 6047 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6048 that would generate a new entry in the nonzero structure instead produces 6049 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 6050 6051 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6052 that would generate a new entry that has not been preallocated will 6053 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6054 only.) This is a useful flag when debugging matrix memory preallocation. 6055 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6056 6057 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6058 other processors should be dropped, rather than stashed. 6059 This is useful if you know that the "owning" processor is also 6060 always generating the correct matrix entries, so that PETSc need 6061 not transfer duplicate entries generated on another processor. 6062 6063 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6064 searches during matrix assembly. When this flag is set, the hash table 6065 is created during the first matrix assembly. This hash table is 6066 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6067 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6068 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6069 supported by `MATMPIBAIJ` format only. 6070 6071 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6072 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6073 6074 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6075 a zero location in the matrix 6076 6077 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6078 6079 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6080 zero row routines and thus improves performance for very large process counts. 6081 6082 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6083 part of the matrix (since they should match the upper triangular part). 6084 6085 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6086 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6087 with finite difference schemes with non-periodic boundary conditions. 6088 6089 Developer Note: 6090 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6091 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6092 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6093 not changed. 6094 6095 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6096 @*/ 6097 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6098 { 6099 PetscFunctionBegin; 6100 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6101 if (op > 0) { 6102 PetscValidLogicalCollectiveEnum(mat, op, 2); 6103 PetscValidLogicalCollectiveBool(mat, flg, 3); 6104 } 6105 6106 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); 6107 6108 switch (op) { 6109 case MAT_FORCE_DIAGONAL_ENTRIES: 6110 mat->force_diagonals = flg; 6111 PetscFunctionReturn(PETSC_SUCCESS); 6112 case MAT_NO_OFF_PROC_ENTRIES: 6113 mat->nooffprocentries = flg; 6114 PetscFunctionReturn(PETSC_SUCCESS); 6115 case MAT_SUBSET_OFF_PROC_ENTRIES: 6116 mat->assembly_subset = flg; 6117 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6118 #if !defined(PETSC_HAVE_MPIUNI) 6119 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6120 #endif 6121 mat->stash.first_assembly_done = PETSC_FALSE; 6122 } 6123 PetscFunctionReturn(PETSC_SUCCESS); 6124 case MAT_NO_OFF_PROC_ZERO_ROWS: 6125 mat->nooffproczerorows = flg; 6126 PetscFunctionReturn(PETSC_SUCCESS); 6127 case MAT_SPD: 6128 if (flg) { 6129 mat->spd = PETSC_BOOL3_TRUE; 6130 mat->symmetric = PETSC_BOOL3_TRUE; 6131 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6132 } else { 6133 mat->spd = PETSC_BOOL3_FALSE; 6134 } 6135 break; 6136 case MAT_SYMMETRIC: 6137 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6138 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6139 #if !defined(PETSC_USE_COMPLEX) 6140 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6141 #endif 6142 break; 6143 case MAT_HERMITIAN: 6144 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6145 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6146 #if !defined(PETSC_USE_COMPLEX) 6147 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6148 #endif 6149 break; 6150 case MAT_STRUCTURALLY_SYMMETRIC: 6151 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6152 break; 6153 case MAT_SYMMETRY_ETERNAL: 6154 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"); 6155 mat->symmetry_eternal = flg; 6156 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6157 break; 6158 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6159 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"); 6160 mat->structural_symmetry_eternal = flg; 6161 break; 6162 case MAT_SPD_ETERNAL: 6163 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"); 6164 mat->spd_eternal = flg; 6165 if (flg) { 6166 mat->structural_symmetry_eternal = PETSC_TRUE; 6167 mat->symmetry_eternal = PETSC_TRUE; 6168 } 6169 break; 6170 case MAT_STRUCTURE_ONLY: 6171 mat->structure_only = flg; 6172 break; 6173 case MAT_SORTED_FULL: 6174 mat->sortedfull = flg; 6175 break; 6176 default: 6177 break; 6178 } 6179 PetscTryTypeMethod(mat, setoption, op, flg); 6180 PetscFunctionReturn(PETSC_SUCCESS); 6181 } 6182 6183 /*@ 6184 MatGetOption - Gets a parameter option that has been set for a matrix. 6185 6186 Logically Collective 6187 6188 Input Parameters: 6189 + mat - the matrix 6190 - op - the option, this only responds to certain options, check the code for which ones 6191 6192 Output Parameter: 6193 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6194 6195 Level: intermediate 6196 6197 Notes: 6198 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6199 6200 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6201 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6202 6203 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6204 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6205 @*/ 6206 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6207 { 6208 PetscFunctionBegin; 6209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6210 PetscValidType(mat, 1); 6211 6212 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); 6213 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()"); 6214 6215 switch (op) { 6216 case MAT_NO_OFF_PROC_ENTRIES: 6217 *flg = mat->nooffprocentries; 6218 break; 6219 case MAT_NO_OFF_PROC_ZERO_ROWS: 6220 *flg = mat->nooffproczerorows; 6221 break; 6222 case MAT_SYMMETRIC: 6223 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6224 break; 6225 case MAT_HERMITIAN: 6226 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6227 break; 6228 case MAT_STRUCTURALLY_SYMMETRIC: 6229 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6230 break; 6231 case MAT_SPD: 6232 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6233 break; 6234 case MAT_SYMMETRY_ETERNAL: 6235 *flg = mat->symmetry_eternal; 6236 break; 6237 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6238 *flg = mat->symmetry_eternal; 6239 break; 6240 default: 6241 break; 6242 } 6243 PetscFunctionReturn(PETSC_SUCCESS); 6244 } 6245 6246 /*@ 6247 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6248 this routine retains the old nonzero structure. 6249 6250 Logically Collective 6251 6252 Input Parameter: 6253 . mat - the matrix 6254 6255 Level: intermediate 6256 6257 Note: 6258 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. 6259 See the Performance chapter of the users manual for information on preallocating matrices. 6260 6261 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6262 @*/ 6263 PetscErrorCode MatZeroEntries(Mat mat) 6264 { 6265 PetscFunctionBegin; 6266 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6267 PetscValidType(mat, 1); 6268 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6269 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"); 6270 MatCheckPreallocated(mat, 1); 6271 6272 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6273 PetscUseTypeMethod(mat, zeroentries); 6274 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6275 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6276 PetscFunctionReturn(PETSC_SUCCESS); 6277 } 6278 6279 /*@ 6280 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6281 of a set of rows and columns of a matrix. 6282 6283 Collective 6284 6285 Input Parameters: 6286 + mat - the matrix 6287 . numRows - the number of rows/columns to zero 6288 . rows - the global row indices 6289 . diag - value put in the diagonal of the eliminated rows 6290 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6291 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6292 6293 Level: intermediate 6294 6295 Notes: 6296 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6297 6298 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6299 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 6300 6301 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6302 Krylov method to take advantage of the known solution on the zeroed rows. 6303 6304 For the parallel case, all processes that share the matrix (i.e., 6305 those in the communicator used for matrix creation) MUST call this 6306 routine, regardless of whether any rows being zeroed are owned by 6307 them. 6308 6309 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6310 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 6311 missing. 6312 6313 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6314 list only rows local to itself). 6315 6316 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6317 6318 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6319 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6320 @*/ 6321 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6322 { 6323 PetscFunctionBegin; 6324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6325 PetscValidType(mat, 1); 6326 if (numRows) PetscAssertPointer(rows, 3); 6327 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6328 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6329 MatCheckPreallocated(mat, 1); 6330 6331 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6332 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6333 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6334 PetscFunctionReturn(PETSC_SUCCESS); 6335 } 6336 6337 /*@ 6338 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6339 of a set of rows and columns of a matrix. 6340 6341 Collective 6342 6343 Input Parameters: 6344 + mat - the matrix 6345 . is - the rows to zero 6346 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6347 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6348 - b - optional vector of right-hand side, that will be adjusted by provided solution 6349 6350 Level: intermediate 6351 6352 Note: 6353 See `MatZeroRowsColumns()` for details on how this routine operates. 6354 6355 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6356 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6357 @*/ 6358 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6359 { 6360 PetscInt numRows; 6361 const PetscInt *rows; 6362 6363 PetscFunctionBegin; 6364 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6365 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6366 PetscValidType(mat, 1); 6367 PetscValidType(is, 2); 6368 PetscCall(ISGetLocalSize(is, &numRows)); 6369 PetscCall(ISGetIndices(is, &rows)); 6370 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6371 PetscCall(ISRestoreIndices(is, &rows)); 6372 PetscFunctionReturn(PETSC_SUCCESS); 6373 } 6374 6375 /*@ 6376 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6377 of a set of rows of a matrix. 6378 6379 Collective 6380 6381 Input Parameters: 6382 + mat - the matrix 6383 . numRows - the number of rows to zero 6384 . rows - the global row indices 6385 . diag - value put in the diagonal of the zeroed rows 6386 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6387 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6388 6389 Level: intermediate 6390 6391 Notes: 6392 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6393 6394 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6395 6396 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6397 Krylov method to take advantage of the known solution on the zeroed rows. 6398 6399 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) 6400 from the matrix. 6401 6402 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6403 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6404 formats this does not alter the nonzero structure. 6405 6406 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6407 of the matrix is not changed the values are 6408 merely zeroed. 6409 6410 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6411 formats can optionally remove the main diagonal entry from the 6412 nonzero structure as well, by passing 0.0 as the final argument). 6413 6414 For the parallel case, all processes that share the matrix (i.e., 6415 those in the communicator used for matrix creation) MUST call this 6416 routine, regardless of whether any rows being zeroed are owned by 6417 them. 6418 6419 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6420 list only rows local to itself). 6421 6422 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6423 owns that are to be zeroed. This saves a global synchronization in the implementation. 6424 6425 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6426 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6427 @*/ 6428 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6429 { 6430 PetscFunctionBegin; 6431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6432 PetscValidType(mat, 1); 6433 if (numRows) PetscAssertPointer(rows, 3); 6434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6436 MatCheckPreallocated(mat, 1); 6437 6438 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6439 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6440 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6441 PetscFunctionReturn(PETSC_SUCCESS); 6442 } 6443 6444 /*@ 6445 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6446 of a set of rows of a matrix indicated by an `IS` 6447 6448 Collective 6449 6450 Input Parameters: 6451 + mat - the matrix 6452 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6453 . diag - value put in all diagonals of eliminated rows 6454 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6455 - b - optional vector of right-hand side, that will be adjusted by provided solution 6456 6457 Level: intermediate 6458 6459 Note: 6460 See `MatZeroRows()` for details on how this routine operates. 6461 6462 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6463 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6464 @*/ 6465 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6466 { 6467 PetscInt numRows = 0; 6468 const PetscInt *rows = NULL; 6469 6470 PetscFunctionBegin; 6471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6472 PetscValidType(mat, 1); 6473 if (is) { 6474 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6475 PetscCall(ISGetLocalSize(is, &numRows)); 6476 PetscCall(ISGetIndices(is, &rows)); 6477 } 6478 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6479 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6480 PetscFunctionReturn(PETSC_SUCCESS); 6481 } 6482 6483 /*@ 6484 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6485 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6486 6487 Collective 6488 6489 Input Parameters: 6490 + mat - the matrix 6491 . numRows - the number of rows to remove 6492 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6493 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6494 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6495 - b - optional vector of right-hand side, that will be adjusted by provided solution 6496 6497 Level: intermediate 6498 6499 Notes: 6500 See `MatZeroRows()` for details on how this routine operates. 6501 6502 The grid coordinates are across the entire grid, not just the local portion 6503 6504 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6505 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6506 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6507 `DM_BOUNDARY_PERIODIC` boundary type. 6508 6509 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 6510 a single value per point) you can skip filling those indices. 6511 6512 Fortran Note: 6513 `idxm` and `idxn` should be declared as 6514 $ MatStencil idxm(4, m) 6515 and the values inserted using 6516 .vb 6517 idxm(MatStencil_i, 1) = i 6518 idxm(MatStencil_j, 1) = j 6519 idxm(MatStencil_k, 1) = k 6520 idxm(MatStencil_c, 1) = c 6521 etc 6522 .ve 6523 6524 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6525 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6526 @*/ 6527 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6528 { 6529 PetscInt dim = mat->stencil.dim; 6530 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6531 PetscInt *dims = mat->stencil.dims + 1; 6532 PetscInt *starts = mat->stencil.starts; 6533 PetscInt *dxm = (PetscInt *)rows; 6534 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6535 6536 PetscFunctionBegin; 6537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6538 PetscValidType(mat, 1); 6539 if (numRows) PetscAssertPointer(rows, 3); 6540 6541 PetscCall(PetscMalloc1(numRows, &jdxm)); 6542 for (i = 0; i < numRows; ++i) { 6543 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6544 for (j = 0; j < 3 - sdim; ++j) dxm++; 6545 /* Local index in X dir */ 6546 tmp = *dxm++ - starts[0]; 6547 /* Loop over remaining dimensions */ 6548 for (j = 0; j < dim - 1; ++j) { 6549 /* If nonlocal, set index to be negative */ 6550 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6551 /* Update local index */ 6552 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6553 } 6554 /* Skip component slot if necessary */ 6555 if (mat->stencil.noc) dxm++; 6556 /* Local row number */ 6557 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6558 } 6559 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6560 PetscCall(PetscFree(jdxm)); 6561 PetscFunctionReturn(PETSC_SUCCESS); 6562 } 6563 6564 /*@ 6565 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6566 of a set of rows and columns of a matrix. 6567 6568 Collective 6569 6570 Input Parameters: 6571 + mat - the matrix 6572 . numRows - the number of rows/columns to remove 6573 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6574 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6575 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6576 - b - optional vector of right-hand side, that will be adjusted by provided solution 6577 6578 Level: intermediate 6579 6580 Notes: 6581 See `MatZeroRowsColumns()` for details on how this routine operates. 6582 6583 The grid coordinates are across the entire grid, not just the local portion 6584 6585 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6586 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6587 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6588 `DM_BOUNDARY_PERIODIC` boundary type. 6589 6590 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 6591 a single value per point) you can skip filling those indices. 6592 6593 Fortran Note: 6594 `idxm` and `idxn` should be declared as 6595 $ MatStencil idxm(4, m) 6596 and the values inserted using 6597 .vb 6598 idxm(MatStencil_i, 1) = i 6599 idxm(MatStencil_j, 1) = j 6600 idxm(MatStencil_k, 1) = k 6601 idxm(MatStencil_c, 1) = c 6602 etc 6603 .ve 6604 6605 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6606 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6607 @*/ 6608 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6609 { 6610 PetscInt dim = mat->stencil.dim; 6611 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6612 PetscInt *dims = mat->stencil.dims + 1; 6613 PetscInt *starts = mat->stencil.starts; 6614 PetscInt *dxm = (PetscInt *)rows; 6615 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6616 6617 PetscFunctionBegin; 6618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6619 PetscValidType(mat, 1); 6620 if (numRows) PetscAssertPointer(rows, 3); 6621 6622 PetscCall(PetscMalloc1(numRows, &jdxm)); 6623 for (i = 0; i < numRows; ++i) { 6624 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6625 for (j = 0; j < 3 - sdim; ++j) dxm++; 6626 /* Local index in X dir */ 6627 tmp = *dxm++ - starts[0]; 6628 /* Loop over remaining dimensions */ 6629 for (j = 0; j < dim - 1; ++j) { 6630 /* If nonlocal, set index to be negative */ 6631 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6632 /* Update local index */ 6633 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6634 } 6635 /* Skip component slot if necessary */ 6636 if (mat->stencil.noc) dxm++; 6637 /* Local row number */ 6638 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6639 } 6640 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6641 PetscCall(PetscFree(jdxm)); 6642 PetscFunctionReturn(PETSC_SUCCESS); 6643 } 6644 6645 /*@ 6646 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6647 of a set of rows of a matrix; using local numbering of rows. 6648 6649 Collective 6650 6651 Input Parameters: 6652 + mat - the matrix 6653 . numRows - the number of rows to remove 6654 . rows - the local row indices 6655 . diag - value put in all diagonals of eliminated rows 6656 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6657 - b - optional vector of right-hand side, that will be adjusted by provided solution 6658 6659 Level: intermediate 6660 6661 Notes: 6662 Before calling `MatZeroRowsLocal()`, the user must first set the 6663 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6664 6665 See `MatZeroRows()` for details on how this routine operates. 6666 6667 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6668 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6669 @*/ 6670 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6671 { 6672 PetscFunctionBegin; 6673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6674 PetscValidType(mat, 1); 6675 if (numRows) PetscAssertPointer(rows, 3); 6676 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6677 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6678 MatCheckPreallocated(mat, 1); 6679 6680 if (mat->ops->zerorowslocal) { 6681 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6682 } else { 6683 IS is, newis; 6684 const PetscInt *newRows; 6685 6686 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6687 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6688 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6689 PetscCall(ISGetIndices(newis, &newRows)); 6690 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6691 PetscCall(ISRestoreIndices(newis, &newRows)); 6692 PetscCall(ISDestroy(&newis)); 6693 PetscCall(ISDestroy(&is)); 6694 } 6695 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6696 PetscFunctionReturn(PETSC_SUCCESS); 6697 } 6698 6699 /*@ 6700 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6701 of a set of rows of a matrix; using local numbering of rows. 6702 6703 Collective 6704 6705 Input Parameters: 6706 + mat - the matrix 6707 . is - index set of rows to remove 6708 . diag - value put in all diagonals of eliminated rows 6709 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6710 - b - optional vector of right-hand side, that will be adjusted by provided solution 6711 6712 Level: intermediate 6713 6714 Notes: 6715 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6716 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6717 6718 See `MatZeroRows()` for details on how this routine operates. 6719 6720 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6721 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6722 @*/ 6723 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6724 { 6725 PetscInt numRows; 6726 const PetscInt *rows; 6727 6728 PetscFunctionBegin; 6729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6730 PetscValidType(mat, 1); 6731 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6734 MatCheckPreallocated(mat, 1); 6735 6736 PetscCall(ISGetLocalSize(is, &numRows)); 6737 PetscCall(ISGetIndices(is, &rows)); 6738 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6739 PetscCall(ISRestoreIndices(is, &rows)); 6740 PetscFunctionReturn(PETSC_SUCCESS); 6741 } 6742 6743 /*@ 6744 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6745 of a set of rows and columns of a matrix; using local numbering of rows. 6746 6747 Collective 6748 6749 Input Parameters: 6750 + mat - the matrix 6751 . numRows - the number of rows to remove 6752 . rows - the global row indices 6753 . diag - value put in all diagonals of eliminated rows 6754 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6755 - b - optional vector of right-hand side, that will be adjusted by provided solution 6756 6757 Level: intermediate 6758 6759 Notes: 6760 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6761 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6762 6763 See `MatZeroRowsColumns()` for details on how this routine operates. 6764 6765 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6766 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6767 @*/ 6768 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6769 { 6770 IS is, newis; 6771 const PetscInt *newRows; 6772 6773 PetscFunctionBegin; 6774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6775 PetscValidType(mat, 1); 6776 if (numRows) PetscAssertPointer(rows, 3); 6777 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6778 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6779 MatCheckPreallocated(mat, 1); 6780 6781 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6782 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6783 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6784 PetscCall(ISGetIndices(newis, &newRows)); 6785 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6786 PetscCall(ISRestoreIndices(newis, &newRows)); 6787 PetscCall(ISDestroy(&newis)); 6788 PetscCall(ISDestroy(&is)); 6789 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6790 PetscFunctionReturn(PETSC_SUCCESS); 6791 } 6792 6793 /*@ 6794 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6795 of a set of rows and columns of a matrix; using local numbering of rows. 6796 6797 Collective 6798 6799 Input Parameters: 6800 + mat - the matrix 6801 . is - index set of rows to remove 6802 . diag - value put in all diagonals of eliminated rows 6803 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6804 - b - optional vector of right-hand side, that will be adjusted by provided solution 6805 6806 Level: intermediate 6807 6808 Notes: 6809 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6810 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6811 6812 See `MatZeroRowsColumns()` for details on how this routine operates. 6813 6814 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6815 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6816 @*/ 6817 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6818 { 6819 PetscInt numRows; 6820 const PetscInt *rows; 6821 6822 PetscFunctionBegin; 6823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6824 PetscValidType(mat, 1); 6825 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6826 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6827 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6828 MatCheckPreallocated(mat, 1); 6829 6830 PetscCall(ISGetLocalSize(is, &numRows)); 6831 PetscCall(ISGetIndices(is, &rows)); 6832 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6833 PetscCall(ISRestoreIndices(is, &rows)); 6834 PetscFunctionReturn(PETSC_SUCCESS); 6835 } 6836 6837 /*@ 6838 MatGetSize - Returns the numbers of rows and columns in a matrix. 6839 6840 Not Collective 6841 6842 Input Parameter: 6843 . mat - the matrix 6844 6845 Output Parameters: 6846 + m - the number of global rows 6847 - n - the number of global columns 6848 6849 Level: beginner 6850 6851 Note: 6852 Both output parameters can be `NULL` on input. 6853 6854 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6855 @*/ 6856 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6857 { 6858 PetscFunctionBegin; 6859 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6860 if (m) *m = mat->rmap->N; 6861 if (n) *n = mat->cmap->N; 6862 PetscFunctionReturn(PETSC_SUCCESS); 6863 } 6864 6865 /*@ 6866 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6867 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6868 6869 Not Collective 6870 6871 Input Parameter: 6872 . mat - the matrix 6873 6874 Output Parameters: 6875 + m - the number of local rows, use `NULL` to not obtain this value 6876 - n - the number of local columns, use `NULL` to not obtain this value 6877 6878 Level: beginner 6879 6880 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6881 @*/ 6882 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6883 { 6884 PetscFunctionBegin; 6885 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6886 if (m) PetscAssertPointer(m, 2); 6887 if (n) PetscAssertPointer(n, 3); 6888 if (m) *m = mat->rmap->n; 6889 if (n) *n = mat->cmap->n; 6890 PetscFunctionReturn(PETSC_SUCCESS); 6891 } 6892 6893 /*@ 6894 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6895 vector one multiplies this matrix by that are owned by this processor. 6896 6897 Not Collective, unless matrix has not been allocated, then collective 6898 6899 Input Parameter: 6900 . mat - the matrix 6901 6902 Output Parameters: 6903 + m - the global index of the first local column, use `NULL` to not obtain this value 6904 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6905 6906 Level: developer 6907 6908 Notes: 6909 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6910 6911 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6912 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6913 6914 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6915 the local values in the matrix. 6916 6917 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6918 Layouts](sec_matlayout) for details on matrix layouts. 6919 6920 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6921 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6922 @*/ 6923 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6924 { 6925 PetscFunctionBegin; 6926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6927 PetscValidType(mat, 1); 6928 if (m) PetscAssertPointer(m, 2); 6929 if (n) PetscAssertPointer(n, 3); 6930 MatCheckPreallocated(mat, 1); 6931 if (m) *m = mat->cmap->rstart; 6932 if (n) *n = mat->cmap->rend; 6933 PetscFunctionReturn(PETSC_SUCCESS); 6934 } 6935 6936 /*@ 6937 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6938 this MPI process. 6939 6940 Not Collective 6941 6942 Input Parameter: 6943 . mat - the matrix 6944 6945 Output Parameters: 6946 + m - the global index of the first local row, use `NULL` to not obtain this value 6947 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6948 6949 Level: beginner 6950 6951 Notes: 6952 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6953 6954 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6955 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6956 6957 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6958 the local values in the matrix. 6959 6960 The high argument is one more than the last element stored locally. 6961 6962 For all matrices it returns the range of matrix rows associated with rows of a vector that 6963 would contain the result of a matrix vector product with this matrix. See [Matrix 6964 Layouts](sec_matlayout) for details on matrix layouts. 6965 6966 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6967 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6968 @*/ 6969 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6970 { 6971 PetscFunctionBegin; 6972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6973 PetscValidType(mat, 1); 6974 if (m) PetscAssertPointer(m, 2); 6975 if (n) PetscAssertPointer(n, 3); 6976 MatCheckPreallocated(mat, 1); 6977 if (m) *m = mat->rmap->rstart; 6978 if (n) *n = mat->rmap->rend; 6979 PetscFunctionReturn(PETSC_SUCCESS); 6980 } 6981 6982 /*@C 6983 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6984 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6985 6986 Not Collective, unless matrix has not been allocated 6987 6988 Input Parameter: 6989 . mat - the matrix 6990 6991 Output Parameter: 6992 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6993 where `size` is the number of MPI processes used by `mat` 6994 6995 Level: beginner 6996 6997 Notes: 6998 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6999 7000 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7001 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7002 7003 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7004 the local values in the matrix. 7005 7006 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 7007 would contain the result of a matrix vector product with this matrix. See [Matrix 7008 Layouts](sec_matlayout) for details on matrix layouts. 7009 7010 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 7011 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 7012 `DMDAGetGhostCorners()`, `DM` 7013 @*/ 7014 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 7015 { 7016 PetscFunctionBegin; 7017 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7018 PetscValidType(mat, 1); 7019 MatCheckPreallocated(mat, 1); 7020 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 7021 PetscFunctionReturn(PETSC_SUCCESS); 7022 } 7023 7024 /*@C 7025 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 7026 vector one multiplies this vector by that are owned by each processor. 7027 7028 Not Collective, unless matrix has not been allocated 7029 7030 Input Parameter: 7031 . mat - the matrix 7032 7033 Output Parameter: 7034 . ranges - start of each processors portion plus one more than the total length at the end 7035 7036 Level: beginner 7037 7038 Notes: 7039 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7040 7041 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7042 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7043 7044 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7045 the local values in the matrix. 7046 7047 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7048 Layouts](sec_matlayout) for details on matrix layouts. 7049 7050 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7051 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7052 `DMDAGetGhostCorners()`, `DM` 7053 @*/ 7054 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7055 { 7056 PetscFunctionBegin; 7057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7058 PetscValidType(mat, 1); 7059 MatCheckPreallocated(mat, 1); 7060 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7061 PetscFunctionReturn(PETSC_SUCCESS); 7062 } 7063 7064 /*@ 7065 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7066 7067 Not Collective 7068 7069 Input Parameter: 7070 . A - matrix 7071 7072 Output Parameters: 7073 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7074 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7075 7076 Level: intermediate 7077 7078 Note: 7079 You should call `ISDestroy()` on the returned `IS` 7080 7081 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7082 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7083 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7084 details on matrix layouts. 7085 7086 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7087 @*/ 7088 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7089 { 7090 PetscErrorCode (*f)(Mat, IS *, IS *); 7091 7092 PetscFunctionBegin; 7093 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7094 PetscValidType(A, 1); 7095 MatCheckPreallocated(A, 1); 7096 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7097 if (f) { 7098 PetscCall((*f)(A, rows, cols)); 7099 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7100 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7101 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7102 } 7103 PetscFunctionReturn(PETSC_SUCCESS); 7104 } 7105 7106 /*@ 7107 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7108 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7109 to complete the factorization. 7110 7111 Collective 7112 7113 Input Parameters: 7114 + fact - the factorized matrix obtained with `MatGetFactor()` 7115 . mat - the matrix 7116 . row - row permutation 7117 . col - column permutation 7118 - info - structure containing 7119 .vb 7120 levels - number of levels of fill. 7121 expected fill - as ratio of original fill. 7122 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7123 missing diagonal entries) 7124 .ve 7125 7126 Level: developer 7127 7128 Notes: 7129 See [Matrix Factorization](sec_matfactor) for additional information. 7130 7131 Most users should employ the `KSP` interface for linear solvers 7132 instead of working directly with matrix algebra routines such as this. 7133 See, e.g., `KSPCreate()`. 7134 7135 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7136 7137 Developer Note: 7138 The Fortran interface is not autogenerated as the 7139 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7140 7141 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7142 `MatGetOrdering()`, `MatFactorInfo` 7143 @*/ 7144 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7145 { 7146 PetscFunctionBegin; 7147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7148 PetscValidType(mat, 2); 7149 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7150 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7151 PetscAssertPointer(info, 5); 7152 PetscAssertPointer(fact, 1); 7153 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7154 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7155 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7156 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7157 MatCheckPreallocated(mat, 2); 7158 7159 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7160 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7162 PetscFunctionReturn(PETSC_SUCCESS); 7163 } 7164 7165 /*@ 7166 MatICCFactorSymbolic - Performs symbolic incomplete 7167 Cholesky factorization for a symmetric matrix. Use 7168 `MatCholeskyFactorNumeric()` to complete the factorization. 7169 7170 Collective 7171 7172 Input Parameters: 7173 + fact - the factorized matrix obtained with `MatGetFactor()` 7174 . mat - the matrix to be factored 7175 . perm - row and column permutation 7176 - info - structure containing 7177 .vb 7178 levels - number of levels of fill. 7179 expected fill - as ratio of original fill. 7180 .ve 7181 7182 Level: developer 7183 7184 Notes: 7185 Most users should employ the `KSP` interface for linear solvers 7186 instead of working directly with matrix algebra routines such as this. 7187 See, e.g., `KSPCreate()`. 7188 7189 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7190 7191 Developer Note: 7192 The Fortran interface is not autogenerated as the 7193 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7194 7195 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7196 @*/ 7197 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7198 { 7199 PetscFunctionBegin; 7200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7201 PetscValidType(mat, 2); 7202 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7203 PetscAssertPointer(info, 4); 7204 PetscAssertPointer(fact, 1); 7205 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7206 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7207 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7209 MatCheckPreallocated(mat, 2); 7210 7211 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7212 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7213 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7214 PetscFunctionReturn(PETSC_SUCCESS); 7215 } 7216 7217 /*@C 7218 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7219 points to an array of valid matrices, they may be reused to store the new 7220 submatrices. 7221 7222 Collective 7223 7224 Input Parameters: 7225 + mat - the matrix 7226 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7227 . irow - index set of rows to extract 7228 . icol - index set of columns to extract 7229 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7230 7231 Output Parameter: 7232 . submat - the array of submatrices 7233 7234 Level: advanced 7235 7236 Notes: 7237 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7238 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7239 to extract a parallel submatrix. 7240 7241 Some matrix types place restrictions on the row and column 7242 indices, such as that they be sorted or that they be equal to each other. 7243 7244 The index sets may not have duplicate entries. 7245 7246 When extracting submatrices from a parallel matrix, each processor can 7247 form a different submatrix by setting the rows and columns of its 7248 individual index sets according to the local submatrix desired. 7249 7250 When finished using the submatrices, the user should destroy 7251 them with `MatDestroySubMatrices()`. 7252 7253 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7254 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7255 7256 This routine creates the matrices in submat; you should NOT create them before 7257 calling it. It also allocates the array of matrix pointers submat. 7258 7259 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7260 request one row/column in a block, they must request all rows/columns that are in 7261 that block. For example, if the block size is 2 you cannot request just row 0 and 7262 column 0. 7263 7264 Fortran Note: 7265 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7266 7267 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7268 @*/ 7269 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7270 { 7271 PetscInt i; 7272 PetscBool eq; 7273 7274 PetscFunctionBegin; 7275 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7276 PetscValidType(mat, 1); 7277 if (n) { 7278 PetscAssertPointer(irow, 3); 7279 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7280 PetscAssertPointer(icol, 4); 7281 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7282 } 7283 PetscAssertPointer(submat, 6); 7284 if (n && scall == MAT_REUSE_MATRIX) { 7285 PetscAssertPointer(*submat, 6); 7286 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7287 } 7288 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7289 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7290 MatCheckPreallocated(mat, 1); 7291 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7292 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7293 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7294 for (i = 0; i < n; i++) { 7295 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7296 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7297 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7298 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7299 if (mat->boundtocpu && mat->bindingpropagates) { 7300 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7301 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7302 } 7303 #endif 7304 } 7305 PetscFunctionReturn(PETSC_SUCCESS); 7306 } 7307 7308 /*@C 7309 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7310 7311 Collective 7312 7313 Input Parameters: 7314 + mat - the matrix 7315 . n - the number of submatrixes to be extracted 7316 . irow - index set of rows to extract 7317 . icol - index set of columns to extract 7318 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7319 7320 Output Parameter: 7321 . submat - the array of submatrices 7322 7323 Level: advanced 7324 7325 Note: 7326 This is used by `PCGASM` 7327 7328 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7329 @*/ 7330 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7331 { 7332 PetscInt i; 7333 PetscBool eq; 7334 7335 PetscFunctionBegin; 7336 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7337 PetscValidType(mat, 1); 7338 if (n) { 7339 PetscAssertPointer(irow, 3); 7340 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7341 PetscAssertPointer(icol, 4); 7342 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7343 } 7344 PetscAssertPointer(submat, 6); 7345 if (n && scall == MAT_REUSE_MATRIX) { 7346 PetscAssertPointer(*submat, 6); 7347 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7348 } 7349 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7350 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7351 MatCheckPreallocated(mat, 1); 7352 7353 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7354 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7355 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7356 for (i = 0; i < n; i++) { 7357 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7358 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7359 } 7360 PetscFunctionReturn(PETSC_SUCCESS); 7361 } 7362 7363 /*@C 7364 MatDestroyMatrices - Destroys an array of matrices. 7365 7366 Collective 7367 7368 Input Parameters: 7369 + n - the number of local matrices 7370 - mat - the matrices (this is a pointer to the array of matrices) 7371 7372 Level: advanced 7373 7374 Notes: 7375 Frees not only the matrices, but also the array that contains the matrices 7376 7377 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7378 7379 Fortran Note: 7380 Does not free the `mat` array. 7381 7382 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7383 @*/ 7384 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7385 { 7386 PetscInt i; 7387 7388 PetscFunctionBegin; 7389 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7390 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7391 PetscAssertPointer(mat, 2); 7392 7393 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7394 7395 /* memory is allocated even if n = 0 */ 7396 PetscCall(PetscFree(*mat)); 7397 PetscFunctionReturn(PETSC_SUCCESS); 7398 } 7399 7400 /*@C 7401 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7402 7403 Collective 7404 7405 Input Parameters: 7406 + n - the number of local matrices 7407 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7408 sequence of `MatCreateSubMatrices()`) 7409 7410 Level: advanced 7411 7412 Note: 7413 Frees not only the matrices, but also the array that contains the matrices 7414 7415 Fortran Note: 7416 Does not free the `mat` array. 7417 7418 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7419 @*/ 7420 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7421 { 7422 Mat mat0; 7423 7424 PetscFunctionBegin; 7425 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7426 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7427 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7428 PetscAssertPointer(mat, 2); 7429 7430 mat0 = (*mat)[0]; 7431 if (mat0 && mat0->ops->destroysubmatrices) { 7432 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7433 } else { 7434 PetscCall(MatDestroyMatrices(n, mat)); 7435 } 7436 PetscFunctionReturn(PETSC_SUCCESS); 7437 } 7438 7439 /*@ 7440 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7441 7442 Collective 7443 7444 Input Parameter: 7445 . mat - the matrix 7446 7447 Output Parameter: 7448 . matstruct - the sequential matrix with the nonzero structure of `mat` 7449 7450 Level: developer 7451 7452 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7453 @*/ 7454 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7455 { 7456 PetscFunctionBegin; 7457 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7458 PetscAssertPointer(matstruct, 2); 7459 7460 PetscValidType(mat, 1); 7461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7462 MatCheckPreallocated(mat, 1); 7463 7464 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7465 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7466 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7467 PetscFunctionReturn(PETSC_SUCCESS); 7468 } 7469 7470 /*@C 7471 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7472 7473 Collective 7474 7475 Input Parameter: 7476 . mat - the matrix 7477 7478 Level: advanced 7479 7480 Note: 7481 This is not needed, one can just call `MatDestroy()` 7482 7483 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7484 @*/ 7485 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7486 { 7487 PetscFunctionBegin; 7488 PetscAssertPointer(mat, 1); 7489 PetscCall(MatDestroy(mat)); 7490 PetscFunctionReturn(PETSC_SUCCESS); 7491 } 7492 7493 /*@ 7494 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7495 replaces the index sets by larger ones that represent submatrices with 7496 additional overlap. 7497 7498 Collective 7499 7500 Input Parameters: 7501 + mat - the matrix 7502 . n - the number of index sets 7503 . is - the array of index sets (these index sets will changed during the call) 7504 - ov - the additional overlap requested 7505 7506 Options Database Key: 7507 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7508 7509 Level: developer 7510 7511 Note: 7512 The computed overlap preserves the matrix block sizes when the blocks are square. 7513 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7514 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7515 7516 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7517 @*/ 7518 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7519 { 7520 PetscInt i, bs, cbs; 7521 7522 PetscFunctionBegin; 7523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7524 PetscValidType(mat, 1); 7525 PetscValidLogicalCollectiveInt(mat, n, 2); 7526 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7527 if (n) { 7528 PetscAssertPointer(is, 3); 7529 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7530 } 7531 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7532 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7533 MatCheckPreallocated(mat, 1); 7534 7535 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7536 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7537 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7538 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7539 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7540 if (bs == cbs) { 7541 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7542 } 7543 PetscFunctionReturn(PETSC_SUCCESS); 7544 } 7545 7546 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7547 7548 /*@ 7549 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7550 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7551 additional overlap. 7552 7553 Collective 7554 7555 Input Parameters: 7556 + mat - the matrix 7557 . n - the number of index sets 7558 . is - the array of index sets (these index sets will changed during the call) 7559 - ov - the additional overlap requested 7560 7561 ` Options Database Key: 7562 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7563 7564 Level: developer 7565 7566 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7567 @*/ 7568 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7569 { 7570 PetscInt i; 7571 7572 PetscFunctionBegin; 7573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7574 PetscValidType(mat, 1); 7575 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7576 if (n) { 7577 PetscAssertPointer(is, 3); 7578 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7579 } 7580 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7581 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7582 MatCheckPreallocated(mat, 1); 7583 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7584 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7585 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7586 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7587 PetscFunctionReturn(PETSC_SUCCESS); 7588 } 7589 7590 /*@ 7591 MatGetBlockSize - Returns the matrix block size. 7592 7593 Not Collective 7594 7595 Input Parameter: 7596 . mat - the matrix 7597 7598 Output Parameter: 7599 . bs - block size 7600 7601 Level: intermediate 7602 7603 Notes: 7604 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7605 7606 If the block size has not been set yet this routine returns 1. 7607 7608 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7609 @*/ 7610 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7611 { 7612 PetscFunctionBegin; 7613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7614 PetscAssertPointer(bs, 2); 7615 *bs = PetscAbs(mat->rmap->bs); 7616 PetscFunctionReturn(PETSC_SUCCESS); 7617 } 7618 7619 /*@ 7620 MatGetBlockSizes - Returns the matrix block row and column sizes. 7621 7622 Not Collective 7623 7624 Input Parameter: 7625 . mat - the matrix 7626 7627 Output Parameters: 7628 + rbs - row block size 7629 - cbs - column block size 7630 7631 Level: intermediate 7632 7633 Notes: 7634 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7635 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7636 7637 If a block size has not been set yet this routine returns 1. 7638 7639 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7640 @*/ 7641 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7642 { 7643 PetscFunctionBegin; 7644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7645 if (rbs) PetscAssertPointer(rbs, 2); 7646 if (cbs) PetscAssertPointer(cbs, 3); 7647 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7648 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7649 PetscFunctionReturn(PETSC_SUCCESS); 7650 } 7651 7652 /*@ 7653 MatSetBlockSize - Sets the matrix block size. 7654 7655 Logically Collective 7656 7657 Input Parameters: 7658 + mat - the matrix 7659 - bs - block size 7660 7661 Level: intermediate 7662 7663 Notes: 7664 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7665 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7666 7667 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7668 is compatible with the matrix local sizes. 7669 7670 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7671 @*/ 7672 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7673 { 7674 PetscFunctionBegin; 7675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7676 PetscValidLogicalCollectiveInt(mat, bs, 2); 7677 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7678 PetscFunctionReturn(PETSC_SUCCESS); 7679 } 7680 7681 typedef struct { 7682 PetscInt n; 7683 IS *is; 7684 Mat *mat; 7685 PetscObjectState nonzerostate; 7686 Mat C; 7687 } EnvelopeData; 7688 7689 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7690 { 7691 EnvelopeData *edata = (EnvelopeData *)*ptr; 7692 7693 PetscFunctionBegin; 7694 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7695 PetscCall(PetscFree(edata->is)); 7696 PetscCall(PetscFree(edata)); 7697 PetscFunctionReturn(PETSC_SUCCESS); 7698 } 7699 7700 /*@ 7701 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7702 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7703 7704 Collective 7705 7706 Input Parameter: 7707 . mat - the matrix 7708 7709 Level: intermediate 7710 7711 Notes: 7712 There can be zeros within the blocks 7713 7714 The blocks can overlap between processes, including laying on more than two processes 7715 7716 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7717 @*/ 7718 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7719 { 7720 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7721 PetscInt *diag, *odiag, sc; 7722 VecScatter scatter; 7723 PetscScalar *seqv; 7724 const PetscScalar *parv; 7725 const PetscInt *ia, *ja; 7726 PetscBool set, flag, done; 7727 Mat AA = mat, A; 7728 MPI_Comm comm; 7729 PetscMPIInt rank, size, tag; 7730 MPI_Status status; 7731 PetscContainer container; 7732 EnvelopeData *edata; 7733 Vec seq, par; 7734 IS isglobal; 7735 7736 PetscFunctionBegin; 7737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7738 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7739 if (!set || !flag) { 7740 /* TODO: only needs nonzero structure of transpose */ 7741 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7742 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7743 } 7744 PetscCall(MatAIJGetLocalMat(AA, &A)); 7745 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7746 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7747 7748 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7749 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7750 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7751 PetscCallMPI(MPI_Comm_size(comm, &size)); 7752 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7753 7754 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7755 7756 if (rank > 0) { 7757 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7758 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7759 } 7760 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7761 for (i = 0; i < n; i++) { 7762 env = PetscMax(env, ja[ia[i + 1] - 1]); 7763 II = rstart + i; 7764 if (env == II) { 7765 starts[lblocks] = tbs; 7766 sizes[lblocks++] = 1 + II - tbs; 7767 tbs = 1 + II; 7768 } 7769 } 7770 if (rank < size - 1) { 7771 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7772 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7773 } 7774 7775 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7776 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7777 PetscCall(MatDestroy(&A)); 7778 7779 PetscCall(PetscNew(&edata)); 7780 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7781 edata->n = lblocks; 7782 /* create IS needed for extracting blocks from the original matrix */ 7783 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7784 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7785 7786 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7787 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7788 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7789 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7790 PetscCall(MatSetType(edata->C, MATAIJ)); 7791 7792 /* Communicate the start and end of each row, from each block to the correct rank */ 7793 /* TODO: Use PetscSF instead of VecScatter */ 7794 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7795 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7796 PetscCall(VecGetArrayWrite(seq, &seqv)); 7797 for (PetscInt i = 0; i < lblocks; i++) { 7798 for (PetscInt j = 0; j < sizes[i]; j++) { 7799 seqv[cnt] = starts[i]; 7800 seqv[cnt + 1] = starts[i] + sizes[i]; 7801 cnt += 2; 7802 } 7803 } 7804 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7805 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7806 sc -= cnt; 7807 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7808 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7809 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7810 PetscCall(ISDestroy(&isglobal)); 7811 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7812 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7813 PetscCall(VecScatterDestroy(&scatter)); 7814 PetscCall(VecDestroy(&seq)); 7815 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7816 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7817 PetscCall(VecGetArrayRead(par, &parv)); 7818 cnt = 0; 7819 PetscCall(MatGetSize(mat, NULL, &n)); 7820 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7821 PetscInt start, end, d = 0, od = 0; 7822 7823 start = (PetscInt)PetscRealPart(parv[cnt]); 7824 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7825 cnt += 2; 7826 7827 if (start < cstart) { 7828 od += cstart - start + n - cend; 7829 d += cend - cstart; 7830 } else if (start < cend) { 7831 od += n - cend; 7832 d += cend - start; 7833 } else od += n - start; 7834 if (end <= cstart) { 7835 od -= cstart - end + n - cend; 7836 d -= cend - cstart; 7837 } else if (end < cend) { 7838 od -= n - cend; 7839 d -= cend - end; 7840 } else od -= n - end; 7841 7842 odiag[i] = od; 7843 diag[i] = d; 7844 } 7845 PetscCall(VecRestoreArrayRead(par, &parv)); 7846 PetscCall(VecDestroy(&par)); 7847 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7848 PetscCall(PetscFree2(diag, odiag)); 7849 PetscCall(PetscFree2(sizes, starts)); 7850 7851 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7852 PetscCall(PetscContainerSetPointer(container, edata)); 7853 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7854 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7855 PetscCall(PetscObjectDereference((PetscObject)container)); 7856 PetscFunctionReturn(PETSC_SUCCESS); 7857 } 7858 7859 /*@ 7860 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7861 7862 Collective 7863 7864 Input Parameters: 7865 + A - the matrix 7866 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7867 7868 Output Parameter: 7869 . C - matrix with inverted block diagonal of `A` 7870 7871 Level: advanced 7872 7873 Note: 7874 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7875 7876 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7877 @*/ 7878 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7879 { 7880 PetscContainer container; 7881 EnvelopeData *edata; 7882 PetscObjectState nonzerostate; 7883 7884 PetscFunctionBegin; 7885 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7886 if (!container) { 7887 PetscCall(MatComputeVariableBlockEnvelope(A)); 7888 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7889 } 7890 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7891 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7892 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7893 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7894 7895 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7896 *C = edata->C; 7897 7898 for (PetscInt i = 0; i < edata->n; i++) { 7899 Mat D; 7900 PetscScalar *dvalues; 7901 7902 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7903 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7904 PetscCall(MatSeqDenseInvert(D)); 7905 PetscCall(MatDenseGetArray(D, &dvalues)); 7906 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7907 PetscCall(MatDestroy(&D)); 7908 } 7909 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7910 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7911 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7912 PetscFunctionReturn(PETSC_SUCCESS); 7913 } 7914 7915 /*@ 7916 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7917 7918 Not Collective 7919 7920 Input Parameters: 7921 + mat - the matrix 7922 . nblocks - the number of blocks on this process, each block can only exist on a single process 7923 - bsizes - the block sizes 7924 7925 Level: intermediate 7926 7927 Notes: 7928 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7929 7930 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. 7931 7932 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7933 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7934 @*/ 7935 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7936 { 7937 PetscInt ncnt = 0, nlocal; 7938 7939 PetscFunctionBegin; 7940 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7941 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7942 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); 7943 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7944 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); 7945 PetscCall(PetscFree(mat->bsizes)); 7946 mat->nblocks = nblocks; 7947 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7948 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7949 PetscFunctionReturn(PETSC_SUCCESS); 7950 } 7951 7952 /*@C 7953 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7954 7955 Not Collective; No Fortran Support 7956 7957 Input Parameter: 7958 . mat - the matrix 7959 7960 Output Parameters: 7961 + nblocks - the number of blocks on this process 7962 - bsizes - the block sizes 7963 7964 Level: intermediate 7965 7966 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7967 @*/ 7968 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7969 { 7970 PetscFunctionBegin; 7971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7972 if (nblocks) *nblocks = mat->nblocks; 7973 if (bsizes) *bsizes = mat->bsizes; 7974 PetscFunctionReturn(PETSC_SUCCESS); 7975 } 7976 7977 /*@ 7978 MatSetBlockSizes - Sets the matrix block row and column sizes. 7979 7980 Logically Collective 7981 7982 Input Parameters: 7983 + mat - the matrix 7984 . rbs - row block size 7985 - cbs - column block size 7986 7987 Level: intermediate 7988 7989 Notes: 7990 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7991 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7992 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7993 7994 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7995 are compatible with the matrix local sizes. 7996 7997 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7998 7999 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 8000 @*/ 8001 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8002 { 8003 PetscFunctionBegin; 8004 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8005 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8006 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8007 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8008 if (mat->rmap->refcnt) { 8009 ISLocalToGlobalMapping l2g = NULL; 8010 PetscLayout nmap = NULL; 8011 8012 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8013 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8014 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8015 mat->rmap = nmap; 8016 mat->rmap->mapping = l2g; 8017 } 8018 if (mat->cmap->refcnt) { 8019 ISLocalToGlobalMapping l2g = NULL; 8020 PetscLayout nmap = NULL; 8021 8022 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8023 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8024 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8025 mat->cmap = nmap; 8026 mat->cmap->mapping = l2g; 8027 } 8028 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8029 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8030 PetscFunctionReturn(PETSC_SUCCESS); 8031 } 8032 8033 /*@ 8034 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8035 8036 Logically Collective 8037 8038 Input Parameters: 8039 + mat - the matrix 8040 . fromRow - matrix from which to copy row block size 8041 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8042 8043 Level: developer 8044 8045 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8046 @*/ 8047 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8048 { 8049 PetscFunctionBegin; 8050 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8051 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8052 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8053 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8054 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8055 PetscFunctionReturn(PETSC_SUCCESS); 8056 } 8057 8058 /*@ 8059 MatResidual - Default routine to calculate the residual r = b - Ax 8060 8061 Collective 8062 8063 Input Parameters: 8064 + mat - the matrix 8065 . b - the right-hand-side 8066 - x - the approximate solution 8067 8068 Output Parameter: 8069 . r - location to store the residual 8070 8071 Level: developer 8072 8073 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8074 @*/ 8075 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8076 { 8077 PetscFunctionBegin; 8078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8079 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8080 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8081 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8082 PetscValidType(mat, 1); 8083 MatCheckPreallocated(mat, 1); 8084 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8085 if (!mat->ops->residual) { 8086 PetscCall(MatMult(mat, x, r)); 8087 PetscCall(VecAYPX(r, -1.0, b)); 8088 } else { 8089 PetscUseTypeMethod(mat, residual, b, x, r); 8090 } 8091 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8092 PetscFunctionReturn(PETSC_SUCCESS); 8093 } 8094 8095 /*MC 8096 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8097 8098 Synopsis: 8099 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8100 8101 Not Collective 8102 8103 Input Parameters: 8104 + A - the matrix 8105 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8106 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8107 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8108 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8109 always used. 8110 8111 Output Parameters: 8112 + n - number of local rows in the (possibly compressed) matrix 8113 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8114 . ja - the column indices 8115 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8116 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8117 8118 Level: developer 8119 8120 Note: 8121 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8122 8123 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8124 M*/ 8125 8126 /*MC 8127 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8128 8129 Synopsis: 8130 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8131 8132 Not Collective 8133 8134 Input Parameters: 8135 + A - the matrix 8136 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8137 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8138 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8139 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8140 always used. 8141 . n - number of local rows in the (possibly compressed) matrix 8142 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8143 . ja - the column indices 8144 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8145 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8146 8147 Level: developer 8148 8149 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8150 M*/ 8151 8152 /*@C 8153 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8154 8155 Collective 8156 8157 Input Parameters: 8158 + mat - the matrix 8159 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8160 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8161 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8162 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8163 always used. 8164 8165 Output Parameters: 8166 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8167 . 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 8168 . ja - the column indices, use `NULL` if not needed 8169 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8170 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8171 8172 Level: developer 8173 8174 Notes: 8175 You CANNOT change any of the ia[] or ja[] values. 8176 8177 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8178 8179 Fortran Notes: 8180 Use 8181 .vb 8182 PetscInt, pointer :: ia(:),ja(:) 8183 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8184 ! Access the ith and jth entries via ia(i) and ja(j) 8185 .ve 8186 8187 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8188 8189 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8190 @*/ 8191 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8192 { 8193 PetscFunctionBegin; 8194 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8195 PetscValidType(mat, 1); 8196 if (n) PetscAssertPointer(n, 5); 8197 if (ia) PetscAssertPointer(ia, 6); 8198 if (ja) PetscAssertPointer(ja, 7); 8199 if (done) PetscAssertPointer(done, 8); 8200 MatCheckPreallocated(mat, 1); 8201 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8202 else { 8203 if (done) *done = PETSC_TRUE; 8204 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8205 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8206 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8207 } 8208 PetscFunctionReturn(PETSC_SUCCESS); 8209 } 8210 8211 /*@C 8212 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8213 8214 Collective 8215 8216 Input Parameters: 8217 + mat - the matrix 8218 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8219 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8220 symmetrized 8221 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8222 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8223 always used. 8224 . n - number of columns in the (possibly compressed) matrix 8225 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8226 - ja - the row indices 8227 8228 Output Parameter: 8229 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8230 8231 Level: developer 8232 8233 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8234 @*/ 8235 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8236 { 8237 PetscFunctionBegin; 8238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8239 PetscValidType(mat, 1); 8240 PetscAssertPointer(n, 5); 8241 if (ia) PetscAssertPointer(ia, 6); 8242 if (ja) PetscAssertPointer(ja, 7); 8243 PetscAssertPointer(done, 8); 8244 MatCheckPreallocated(mat, 1); 8245 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8246 else { 8247 *done = PETSC_TRUE; 8248 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8249 } 8250 PetscFunctionReturn(PETSC_SUCCESS); 8251 } 8252 8253 /*@C 8254 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8255 8256 Collective 8257 8258 Input Parameters: 8259 + mat - the matrix 8260 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8261 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8262 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8263 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8264 always used. 8265 . n - size of (possibly compressed) matrix 8266 . ia - the row pointers 8267 - ja - the column indices 8268 8269 Output Parameter: 8270 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8271 8272 Level: developer 8273 8274 Note: 8275 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8276 us of the array after it has been restored. If you pass `NULL`, it will 8277 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8278 8279 Fortran Note: 8280 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8281 8282 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8283 @*/ 8284 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8285 { 8286 PetscFunctionBegin; 8287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8288 PetscValidType(mat, 1); 8289 if (ia) PetscAssertPointer(ia, 6); 8290 if (ja) PetscAssertPointer(ja, 7); 8291 if (done) PetscAssertPointer(done, 8); 8292 MatCheckPreallocated(mat, 1); 8293 8294 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8295 else { 8296 if (done) *done = PETSC_TRUE; 8297 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8298 if (n) *n = 0; 8299 if (ia) *ia = NULL; 8300 if (ja) *ja = NULL; 8301 } 8302 PetscFunctionReturn(PETSC_SUCCESS); 8303 } 8304 8305 /*@C 8306 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8307 8308 Collective 8309 8310 Input Parameters: 8311 + mat - the matrix 8312 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8313 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8314 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8315 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8316 always used. 8317 8318 Output Parameters: 8319 + n - size of (possibly compressed) matrix 8320 . ia - the column pointers 8321 . ja - the row indices 8322 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8323 8324 Level: developer 8325 8326 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8327 @*/ 8328 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8329 { 8330 PetscFunctionBegin; 8331 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8332 PetscValidType(mat, 1); 8333 if (ia) PetscAssertPointer(ia, 6); 8334 if (ja) PetscAssertPointer(ja, 7); 8335 PetscAssertPointer(done, 8); 8336 MatCheckPreallocated(mat, 1); 8337 8338 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8339 else { 8340 *done = PETSC_TRUE; 8341 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8342 if (n) *n = 0; 8343 if (ia) *ia = NULL; 8344 if (ja) *ja = NULL; 8345 } 8346 PetscFunctionReturn(PETSC_SUCCESS); 8347 } 8348 8349 /*@ 8350 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8351 `MatGetColumnIJ()`. 8352 8353 Collective 8354 8355 Input Parameters: 8356 + mat - the matrix 8357 . ncolors - maximum color value 8358 . n - number of entries in colorarray 8359 - colorarray - array indicating color for each column 8360 8361 Output Parameter: 8362 . iscoloring - coloring generated using colorarray information 8363 8364 Level: developer 8365 8366 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8367 @*/ 8368 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8369 { 8370 PetscFunctionBegin; 8371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8372 PetscValidType(mat, 1); 8373 PetscAssertPointer(colorarray, 4); 8374 PetscAssertPointer(iscoloring, 5); 8375 MatCheckPreallocated(mat, 1); 8376 8377 if (!mat->ops->coloringpatch) { 8378 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8379 } else { 8380 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8381 } 8382 PetscFunctionReturn(PETSC_SUCCESS); 8383 } 8384 8385 /*@ 8386 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8387 8388 Logically Collective 8389 8390 Input Parameter: 8391 . mat - the factored matrix to be reset 8392 8393 Level: developer 8394 8395 Notes: 8396 This routine should be used only with factored matrices formed by in-place 8397 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8398 format). This option can save memory, for example, when solving nonlinear 8399 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8400 ILU(0) preconditioner. 8401 8402 One can specify in-place ILU(0) factorization by calling 8403 .vb 8404 PCType(pc,PCILU); 8405 PCFactorSeUseInPlace(pc); 8406 .ve 8407 or by using the options -pc_type ilu -pc_factor_in_place 8408 8409 In-place factorization ILU(0) can also be used as a local 8410 solver for the blocks within the block Jacobi or additive Schwarz 8411 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8412 for details on setting local solver options. 8413 8414 Most users should employ the `KSP` interface for linear solvers 8415 instead of working directly with matrix algebra routines such as this. 8416 See, e.g., `KSPCreate()`. 8417 8418 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8419 @*/ 8420 PetscErrorCode MatSetUnfactored(Mat mat) 8421 { 8422 PetscFunctionBegin; 8423 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8424 PetscValidType(mat, 1); 8425 MatCheckPreallocated(mat, 1); 8426 mat->factortype = MAT_FACTOR_NONE; 8427 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8428 PetscUseTypeMethod(mat, setunfactored); 8429 PetscFunctionReturn(PETSC_SUCCESS); 8430 } 8431 8432 /*MC 8433 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8434 8435 Synopsis: 8436 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8437 8438 Not Collective 8439 8440 Input Parameter: 8441 . x - matrix 8442 8443 Output Parameters: 8444 + xx_v - the Fortran pointer to the array 8445 - ierr - error code 8446 8447 Example of Usage: 8448 .vb 8449 PetscScalar, pointer xx_v(:,:) 8450 .... 8451 call MatDenseGetArrayF90(x,xx_v,ierr) 8452 a = xx_v(3) 8453 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8454 .ve 8455 8456 Level: advanced 8457 8458 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8459 M*/ 8460 8461 /*MC 8462 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8463 accessed with `MatDenseGetArrayF90()`. 8464 8465 Synopsis: 8466 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8467 8468 Not Collective 8469 8470 Input Parameters: 8471 + x - matrix 8472 - xx_v - the Fortran90 pointer to the array 8473 8474 Output Parameter: 8475 . ierr - error code 8476 8477 Example of Usage: 8478 .vb 8479 PetscScalar, pointer xx_v(:,:) 8480 .... 8481 call MatDenseGetArrayF90(x,xx_v,ierr) 8482 a = xx_v(3) 8483 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8484 .ve 8485 8486 Level: advanced 8487 8488 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8489 M*/ 8490 8491 /*MC 8492 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8493 8494 Synopsis: 8495 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8496 8497 Not Collective 8498 8499 Input Parameter: 8500 . x - matrix 8501 8502 Output Parameters: 8503 + xx_v - the Fortran pointer to the array 8504 - ierr - error code 8505 8506 Example of Usage: 8507 .vb 8508 PetscScalar, pointer xx_v(:) 8509 .... 8510 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8511 a = xx_v(3) 8512 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8513 .ve 8514 8515 Level: advanced 8516 8517 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8518 M*/ 8519 8520 /*MC 8521 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8522 accessed with `MatSeqAIJGetArrayF90()`. 8523 8524 Synopsis: 8525 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8526 8527 Not Collective 8528 8529 Input Parameters: 8530 + x - matrix 8531 - xx_v - the Fortran90 pointer to the array 8532 8533 Output Parameter: 8534 . ierr - error code 8535 8536 Example of Usage: 8537 .vb 8538 PetscScalar, pointer xx_v(:) 8539 .... 8540 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8541 a = xx_v(3) 8542 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8543 .ve 8544 8545 Level: advanced 8546 8547 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8548 M*/ 8549 8550 /*@ 8551 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8552 as the original matrix. 8553 8554 Collective 8555 8556 Input Parameters: 8557 + mat - the original matrix 8558 . isrow - parallel `IS` containing the rows this processor should obtain 8559 . 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. 8560 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8561 8562 Output Parameter: 8563 . newmat - the new submatrix, of the same type as the original matrix 8564 8565 Level: advanced 8566 8567 Notes: 8568 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8569 8570 Some matrix types place restrictions on the row and column indices, such 8571 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; 8572 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8573 8574 The index sets may not have duplicate entries. 8575 8576 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8577 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8578 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8579 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8580 you are finished using it. 8581 8582 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8583 the input matrix. 8584 8585 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8586 8587 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8588 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8589 8590 Example usage: 8591 Consider the following 8x8 matrix with 34 non-zero values, that is 8592 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8593 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8594 as follows 8595 .vb 8596 1 2 0 | 0 3 0 | 0 4 8597 Proc0 0 5 6 | 7 0 0 | 8 0 8598 9 0 10 | 11 0 0 | 12 0 8599 ------------------------------------- 8600 13 0 14 | 15 16 17 | 0 0 8601 Proc1 0 18 0 | 19 20 21 | 0 0 8602 0 0 0 | 22 23 0 | 24 0 8603 ------------------------------------- 8604 Proc2 25 26 27 | 0 0 28 | 29 0 8605 30 0 0 | 31 32 33 | 0 34 8606 .ve 8607 8608 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8609 8610 .vb 8611 2 0 | 0 3 0 | 0 8612 Proc0 5 6 | 7 0 0 | 8 8613 ------------------------------- 8614 Proc1 18 0 | 19 20 21 | 0 8615 ------------------------------- 8616 Proc2 26 27 | 0 0 28 | 29 8617 0 0 | 31 32 33 | 0 8618 .ve 8619 8620 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8621 @*/ 8622 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8623 { 8624 PetscMPIInt size; 8625 Mat *local; 8626 IS iscoltmp; 8627 PetscBool flg; 8628 8629 PetscFunctionBegin; 8630 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8631 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8632 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8633 PetscAssertPointer(newmat, 5); 8634 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8635 PetscValidType(mat, 1); 8636 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8637 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8638 8639 MatCheckPreallocated(mat, 1); 8640 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8641 8642 if (!iscol || isrow == iscol) { 8643 PetscBool stride; 8644 PetscMPIInt grabentirematrix = 0, grab; 8645 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8646 if (stride) { 8647 PetscInt first, step, n, rstart, rend; 8648 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8649 if (step == 1) { 8650 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8651 if (rstart == first) { 8652 PetscCall(ISGetLocalSize(isrow, &n)); 8653 if (n == rend - rstart) grabentirematrix = 1; 8654 } 8655 } 8656 } 8657 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8658 if (grab) { 8659 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8660 if (cll == MAT_INITIAL_MATRIX) { 8661 *newmat = mat; 8662 PetscCall(PetscObjectReference((PetscObject)mat)); 8663 } 8664 PetscFunctionReturn(PETSC_SUCCESS); 8665 } 8666 } 8667 8668 if (!iscol) { 8669 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8670 } else { 8671 iscoltmp = iscol; 8672 } 8673 8674 /* if original matrix is on just one processor then use submatrix generated */ 8675 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8676 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8677 goto setproperties; 8678 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8679 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8680 *newmat = *local; 8681 PetscCall(PetscFree(local)); 8682 goto setproperties; 8683 } else if (!mat->ops->createsubmatrix) { 8684 /* Create a new matrix type that implements the operation using the full matrix */ 8685 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8686 switch (cll) { 8687 case MAT_INITIAL_MATRIX: 8688 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8689 break; 8690 case MAT_REUSE_MATRIX: 8691 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8692 break; 8693 default: 8694 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8695 } 8696 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8697 goto setproperties; 8698 } 8699 8700 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8701 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8702 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8703 8704 setproperties: 8705 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8706 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8707 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8708 } 8709 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8710 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8711 PetscFunctionReturn(PETSC_SUCCESS); 8712 } 8713 8714 /*@ 8715 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8716 8717 Not Collective 8718 8719 Input Parameters: 8720 + A - the matrix we wish to propagate options from 8721 - B - the matrix we wish to propagate options to 8722 8723 Level: beginner 8724 8725 Note: 8726 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8727 8728 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8729 @*/ 8730 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8731 { 8732 PetscFunctionBegin; 8733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8734 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8735 B->symmetry_eternal = A->symmetry_eternal; 8736 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8737 B->symmetric = A->symmetric; 8738 B->structurally_symmetric = A->structurally_symmetric; 8739 B->spd = A->spd; 8740 B->hermitian = A->hermitian; 8741 PetscFunctionReturn(PETSC_SUCCESS); 8742 } 8743 8744 /*@ 8745 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8746 used during the assembly process to store values that belong to 8747 other processors. 8748 8749 Not Collective 8750 8751 Input Parameters: 8752 + mat - the matrix 8753 . size - the initial size of the stash. 8754 - bsize - the initial size of the block-stash(if used). 8755 8756 Options Database Keys: 8757 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8758 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8759 8760 Level: intermediate 8761 8762 Notes: 8763 The block-stash is used for values set with `MatSetValuesBlocked()` while 8764 the stash is used for values set with `MatSetValues()` 8765 8766 Run with the option -info and look for output of the form 8767 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8768 to determine the appropriate value, MM, to use for size and 8769 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8770 to determine the value, BMM to use for bsize 8771 8772 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8773 @*/ 8774 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8775 { 8776 PetscFunctionBegin; 8777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8778 PetscValidType(mat, 1); 8779 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8780 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8781 PetscFunctionReturn(PETSC_SUCCESS); 8782 } 8783 8784 /*@ 8785 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8786 the matrix 8787 8788 Neighbor-wise Collective 8789 8790 Input Parameters: 8791 + A - the matrix 8792 . x - the vector to be multiplied by the interpolation operator 8793 - y - the vector to be added to the result 8794 8795 Output Parameter: 8796 . w - the resulting vector 8797 8798 Level: intermediate 8799 8800 Notes: 8801 `w` may be the same vector as `y`. 8802 8803 This allows one to use either the restriction or interpolation (its transpose) 8804 matrix to do the interpolation 8805 8806 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8807 @*/ 8808 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8809 { 8810 PetscInt M, N, Ny; 8811 8812 PetscFunctionBegin; 8813 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8814 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8815 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8816 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8817 PetscCall(MatGetSize(A, &M, &N)); 8818 PetscCall(VecGetSize(y, &Ny)); 8819 if (M == Ny) { 8820 PetscCall(MatMultAdd(A, x, y, w)); 8821 } else { 8822 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8823 } 8824 PetscFunctionReturn(PETSC_SUCCESS); 8825 } 8826 8827 /*@ 8828 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8829 the matrix 8830 8831 Neighbor-wise Collective 8832 8833 Input Parameters: 8834 + A - the matrix 8835 - x - the vector to be interpolated 8836 8837 Output Parameter: 8838 . y - the resulting vector 8839 8840 Level: intermediate 8841 8842 Note: 8843 This allows one to use either the restriction or interpolation (its transpose) 8844 matrix to do the interpolation 8845 8846 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8847 @*/ 8848 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8849 { 8850 PetscInt M, N, Ny; 8851 8852 PetscFunctionBegin; 8853 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8854 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8855 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8856 PetscCall(MatGetSize(A, &M, &N)); 8857 PetscCall(VecGetSize(y, &Ny)); 8858 if (M == Ny) { 8859 PetscCall(MatMult(A, x, y)); 8860 } else { 8861 PetscCall(MatMultTranspose(A, x, y)); 8862 } 8863 PetscFunctionReturn(PETSC_SUCCESS); 8864 } 8865 8866 /*@ 8867 MatRestrict - $y = A*x$ or $A^T*x$ 8868 8869 Neighbor-wise Collective 8870 8871 Input Parameters: 8872 + A - the matrix 8873 - x - the vector to be restricted 8874 8875 Output Parameter: 8876 . y - the resulting vector 8877 8878 Level: intermediate 8879 8880 Note: 8881 This allows one to use either the restriction or interpolation (its transpose) 8882 matrix to do the restriction 8883 8884 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8885 @*/ 8886 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8887 { 8888 PetscInt M, N, Nx; 8889 8890 PetscFunctionBegin; 8891 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8892 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8893 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8894 PetscCall(MatGetSize(A, &M, &N)); 8895 PetscCall(VecGetSize(x, &Nx)); 8896 if (M == Nx) { 8897 PetscCall(MatMultTranspose(A, x, y)); 8898 } else { 8899 PetscCall(MatMult(A, x, y)); 8900 } 8901 PetscFunctionReturn(PETSC_SUCCESS); 8902 } 8903 8904 /*@ 8905 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8906 8907 Neighbor-wise Collective 8908 8909 Input Parameters: 8910 + A - the matrix 8911 . x - the input dense matrix to be multiplied 8912 - w - the input dense matrix to be added to the result 8913 8914 Output Parameter: 8915 . y - the output dense matrix 8916 8917 Level: intermediate 8918 8919 Note: 8920 This allows one to use either the restriction or interpolation (its transpose) 8921 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8922 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8923 8924 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8925 @*/ 8926 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8927 { 8928 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8929 PetscBool trans = PETSC_TRUE; 8930 MatReuse reuse = MAT_INITIAL_MATRIX; 8931 8932 PetscFunctionBegin; 8933 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8934 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8935 PetscValidType(x, 2); 8936 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8937 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8938 PetscCall(MatGetSize(A, &M, &N)); 8939 PetscCall(MatGetSize(x, &Mx, &Nx)); 8940 if (N == Mx) trans = PETSC_FALSE; 8941 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); 8942 Mo = trans ? N : M; 8943 if (*y) { 8944 PetscCall(MatGetSize(*y, &My, &Ny)); 8945 if (Mo == My && Nx == Ny) { 8946 reuse = MAT_REUSE_MATRIX; 8947 } else { 8948 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); 8949 PetscCall(MatDestroy(y)); 8950 } 8951 } 8952 8953 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8954 PetscBool flg; 8955 8956 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8957 if (w) { 8958 PetscInt My, Ny, Mw, Nw; 8959 8960 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8961 PetscCall(MatGetSize(*y, &My, &Ny)); 8962 PetscCall(MatGetSize(w, &Mw, &Nw)); 8963 if (!flg || My != Mw || Ny != Nw) w = NULL; 8964 } 8965 if (!w) { 8966 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8967 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8968 PetscCall(PetscObjectDereference((PetscObject)w)); 8969 } else { 8970 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8971 } 8972 } 8973 if (!trans) { 8974 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8975 } else { 8976 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8977 } 8978 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8979 PetscFunctionReturn(PETSC_SUCCESS); 8980 } 8981 8982 /*@ 8983 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8984 8985 Neighbor-wise Collective 8986 8987 Input Parameters: 8988 + A - the matrix 8989 - x - the input dense matrix 8990 8991 Output Parameter: 8992 . y - the output dense matrix 8993 8994 Level: intermediate 8995 8996 Note: 8997 This allows one to use either the restriction or interpolation (its transpose) 8998 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8999 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 9000 9001 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 9002 @*/ 9003 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 9004 { 9005 PetscFunctionBegin; 9006 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9007 PetscFunctionReturn(PETSC_SUCCESS); 9008 } 9009 9010 /*@ 9011 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 9012 9013 Neighbor-wise Collective 9014 9015 Input Parameters: 9016 + A - the matrix 9017 - x - the input dense matrix 9018 9019 Output Parameter: 9020 . y - the output dense matrix 9021 9022 Level: intermediate 9023 9024 Note: 9025 This allows one to use either the restriction or interpolation (its transpose) 9026 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 9027 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 9028 9029 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 9030 @*/ 9031 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 9032 { 9033 PetscFunctionBegin; 9034 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9035 PetscFunctionReturn(PETSC_SUCCESS); 9036 } 9037 9038 /*@ 9039 MatGetNullSpace - retrieves the null space of a matrix. 9040 9041 Logically Collective 9042 9043 Input Parameters: 9044 + mat - the matrix 9045 - nullsp - the null space object 9046 9047 Level: developer 9048 9049 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 9050 @*/ 9051 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 9052 { 9053 PetscFunctionBegin; 9054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9055 PetscAssertPointer(nullsp, 2); 9056 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 9057 PetscFunctionReturn(PETSC_SUCCESS); 9058 } 9059 9060 /*@C 9061 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9062 9063 Logically Collective 9064 9065 Input Parameters: 9066 + n - the number of matrices 9067 - mat - the array of matrices 9068 9069 Output Parameters: 9070 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9071 9072 Level: developer 9073 9074 Note: 9075 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9076 9077 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9078 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9079 @*/ 9080 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9081 { 9082 PetscFunctionBegin; 9083 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9084 PetscAssertPointer(mat, 2); 9085 PetscAssertPointer(nullsp, 3); 9086 9087 PetscCall(PetscCalloc1(3 * n, nullsp)); 9088 for (PetscInt i = 0; i < n; i++) { 9089 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9090 (*nullsp)[i] = mat[i]->nullsp; 9091 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9092 (*nullsp)[n + i] = mat[i]->nearnullsp; 9093 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9094 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9095 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9096 } 9097 PetscFunctionReturn(PETSC_SUCCESS); 9098 } 9099 9100 /*@C 9101 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9102 9103 Logically Collective 9104 9105 Input Parameters: 9106 + n - the number of matrices 9107 . mat - the array of matrices 9108 - nullsp - an array of null spaces 9109 9110 Level: developer 9111 9112 Note: 9113 Call `MatGetNullSpaces()` to create `nullsp` 9114 9115 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9116 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9117 @*/ 9118 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9119 { 9120 PetscFunctionBegin; 9121 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9122 PetscAssertPointer(mat, 2); 9123 PetscAssertPointer(nullsp, 3); 9124 PetscAssertPointer(*nullsp, 3); 9125 9126 for (PetscInt i = 0; i < n; i++) { 9127 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9128 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9129 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9130 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9131 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9132 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9133 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9134 } 9135 PetscCall(PetscFree(*nullsp)); 9136 PetscFunctionReturn(PETSC_SUCCESS); 9137 } 9138 9139 /*@ 9140 MatSetNullSpace - attaches a null space to a matrix. 9141 9142 Logically Collective 9143 9144 Input Parameters: 9145 + mat - the matrix 9146 - nullsp - the null space object 9147 9148 Level: advanced 9149 9150 Notes: 9151 This null space is used by the `KSP` linear solvers to solve singular systems. 9152 9153 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` 9154 9155 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 9156 to zero but the linear system will still be solved in a least squares sense. 9157 9158 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9159 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)$. 9160 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 9161 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 9162 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$). 9163 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9164 9165 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9166 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9167 routine also automatically calls `MatSetTransposeNullSpace()`. 9168 9169 The user should call `MatNullSpaceDestroy()`. 9170 9171 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9172 `KSPSetPCSide()` 9173 @*/ 9174 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9175 { 9176 PetscFunctionBegin; 9177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9178 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9179 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9180 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9181 mat->nullsp = nullsp; 9182 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9183 PetscFunctionReturn(PETSC_SUCCESS); 9184 } 9185 9186 /*@ 9187 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9188 9189 Logically Collective 9190 9191 Input Parameters: 9192 + mat - the matrix 9193 - nullsp - the null space object 9194 9195 Level: developer 9196 9197 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9198 @*/ 9199 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9200 { 9201 PetscFunctionBegin; 9202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9203 PetscValidType(mat, 1); 9204 PetscAssertPointer(nullsp, 2); 9205 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9206 PetscFunctionReturn(PETSC_SUCCESS); 9207 } 9208 9209 /*@ 9210 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9211 9212 Logically Collective 9213 9214 Input Parameters: 9215 + mat - the matrix 9216 - nullsp - the null space object 9217 9218 Level: advanced 9219 9220 Notes: 9221 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9222 9223 See `MatSetNullSpace()` 9224 9225 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9226 @*/ 9227 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9228 { 9229 PetscFunctionBegin; 9230 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9231 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9232 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9233 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9234 mat->transnullsp = nullsp; 9235 PetscFunctionReturn(PETSC_SUCCESS); 9236 } 9237 9238 /*@ 9239 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9240 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9241 9242 Logically Collective 9243 9244 Input Parameters: 9245 + mat - the matrix 9246 - nullsp - the null space object 9247 9248 Level: advanced 9249 9250 Notes: 9251 Overwrites any previous near null space that may have been attached 9252 9253 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9254 9255 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9256 @*/ 9257 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9258 { 9259 PetscFunctionBegin; 9260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9261 PetscValidType(mat, 1); 9262 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9263 MatCheckPreallocated(mat, 1); 9264 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9265 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9266 mat->nearnullsp = nullsp; 9267 PetscFunctionReturn(PETSC_SUCCESS); 9268 } 9269 9270 /*@ 9271 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9272 9273 Not Collective 9274 9275 Input Parameter: 9276 . mat - the matrix 9277 9278 Output Parameter: 9279 . nullsp - the null space object, `NULL` if not set 9280 9281 Level: advanced 9282 9283 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9284 @*/ 9285 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9286 { 9287 PetscFunctionBegin; 9288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9289 PetscValidType(mat, 1); 9290 PetscAssertPointer(nullsp, 2); 9291 MatCheckPreallocated(mat, 1); 9292 *nullsp = mat->nearnullsp; 9293 PetscFunctionReturn(PETSC_SUCCESS); 9294 } 9295 9296 /*@ 9297 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9298 9299 Collective 9300 9301 Input Parameters: 9302 + mat - the matrix 9303 . row - row/column permutation 9304 - info - information on desired factorization process 9305 9306 Level: developer 9307 9308 Notes: 9309 Probably really in-place only when level of fill is zero, otherwise allocates 9310 new space to store factored matrix and deletes previous memory. 9311 9312 Most users should employ the `KSP` interface for linear solvers 9313 instead of working directly with matrix algebra routines such as this. 9314 See, e.g., `KSPCreate()`. 9315 9316 Developer Note: 9317 The Fortran interface is not autogenerated as the 9318 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9319 9320 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9321 @*/ 9322 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9323 { 9324 PetscFunctionBegin; 9325 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9326 PetscValidType(mat, 1); 9327 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9328 PetscAssertPointer(info, 3); 9329 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9330 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9331 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9332 MatCheckPreallocated(mat, 1); 9333 PetscUseTypeMethod(mat, iccfactor, row, info); 9334 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9335 PetscFunctionReturn(PETSC_SUCCESS); 9336 } 9337 9338 /*@ 9339 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9340 ghosted ones. 9341 9342 Not Collective 9343 9344 Input Parameters: 9345 + mat - the matrix 9346 - diag - the diagonal values, including ghost ones 9347 9348 Level: developer 9349 9350 Notes: 9351 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9352 9353 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9354 9355 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9356 @*/ 9357 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9358 { 9359 PetscMPIInt size; 9360 9361 PetscFunctionBegin; 9362 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9363 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9364 PetscValidType(mat, 1); 9365 9366 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9367 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9368 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9369 if (size == 1) { 9370 PetscInt n, m; 9371 PetscCall(VecGetSize(diag, &n)); 9372 PetscCall(MatGetSize(mat, NULL, &m)); 9373 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9374 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9375 } else { 9376 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9377 } 9378 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9379 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9380 PetscFunctionReturn(PETSC_SUCCESS); 9381 } 9382 9383 /*@ 9384 MatGetInertia - Gets the inertia from a factored matrix 9385 9386 Collective 9387 9388 Input Parameter: 9389 . mat - the matrix 9390 9391 Output Parameters: 9392 + nneg - number of negative eigenvalues 9393 . nzero - number of zero eigenvalues 9394 - npos - number of positive eigenvalues 9395 9396 Level: advanced 9397 9398 Note: 9399 Matrix must have been factored by `MatCholeskyFactor()` 9400 9401 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9402 @*/ 9403 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9404 { 9405 PetscFunctionBegin; 9406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9407 PetscValidType(mat, 1); 9408 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9409 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9410 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9411 PetscFunctionReturn(PETSC_SUCCESS); 9412 } 9413 9414 /*@C 9415 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9416 9417 Neighbor-wise Collective 9418 9419 Input Parameters: 9420 + mat - the factored matrix obtained with `MatGetFactor()` 9421 - b - the right-hand-side vectors 9422 9423 Output Parameter: 9424 . x - the result vectors 9425 9426 Level: developer 9427 9428 Note: 9429 The vectors `b` and `x` cannot be the same. I.e., one cannot 9430 call `MatSolves`(A,x,x). 9431 9432 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9433 @*/ 9434 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9435 { 9436 PetscFunctionBegin; 9437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9438 PetscValidType(mat, 1); 9439 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9440 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9441 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9442 9443 MatCheckPreallocated(mat, 1); 9444 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9445 PetscUseTypeMethod(mat, solves, b, x); 9446 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9447 PetscFunctionReturn(PETSC_SUCCESS); 9448 } 9449 9450 /*@ 9451 MatIsSymmetric - Test whether a matrix is symmetric 9452 9453 Collective 9454 9455 Input Parameters: 9456 + A - the matrix to test 9457 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9458 9459 Output Parameter: 9460 . flg - the result 9461 9462 Level: intermediate 9463 9464 Notes: 9465 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9466 9467 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9468 9469 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9470 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9471 9472 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9473 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9474 @*/ 9475 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9476 { 9477 PetscFunctionBegin; 9478 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9479 PetscAssertPointer(flg, 3); 9480 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9481 else { 9482 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9483 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9484 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9485 } 9486 PetscFunctionReturn(PETSC_SUCCESS); 9487 } 9488 9489 /*@ 9490 MatIsHermitian - Test whether a matrix is Hermitian 9491 9492 Collective 9493 9494 Input Parameters: 9495 + A - the matrix to test 9496 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9497 9498 Output Parameter: 9499 . flg - the result 9500 9501 Level: intermediate 9502 9503 Notes: 9504 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9505 9506 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9507 9508 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9509 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9510 9511 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9512 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9513 @*/ 9514 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9515 { 9516 PetscFunctionBegin; 9517 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9518 PetscAssertPointer(flg, 3); 9519 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9520 else { 9521 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9522 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9523 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9524 } 9525 PetscFunctionReturn(PETSC_SUCCESS); 9526 } 9527 9528 /*@ 9529 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9530 9531 Not Collective 9532 9533 Input Parameter: 9534 . A - the matrix to check 9535 9536 Output Parameters: 9537 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9538 - flg - the result (only valid if set is `PETSC_TRUE`) 9539 9540 Level: advanced 9541 9542 Notes: 9543 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9544 if you want it explicitly checked 9545 9546 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9547 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9548 9549 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9550 @*/ 9551 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9552 { 9553 PetscFunctionBegin; 9554 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9555 PetscAssertPointer(set, 2); 9556 PetscAssertPointer(flg, 3); 9557 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9558 *set = PETSC_TRUE; 9559 *flg = PetscBool3ToBool(A->symmetric); 9560 } else { 9561 *set = PETSC_FALSE; 9562 } 9563 PetscFunctionReturn(PETSC_SUCCESS); 9564 } 9565 9566 /*@ 9567 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9568 9569 Not Collective 9570 9571 Input Parameter: 9572 . A - the matrix to check 9573 9574 Output Parameters: 9575 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9576 - flg - the result (only valid if set is `PETSC_TRUE`) 9577 9578 Level: advanced 9579 9580 Notes: 9581 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9582 9583 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9584 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9585 9586 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9587 @*/ 9588 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9589 { 9590 PetscFunctionBegin; 9591 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9592 PetscAssertPointer(set, 2); 9593 PetscAssertPointer(flg, 3); 9594 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9595 *set = PETSC_TRUE; 9596 *flg = PetscBool3ToBool(A->spd); 9597 } else { 9598 *set = PETSC_FALSE; 9599 } 9600 PetscFunctionReturn(PETSC_SUCCESS); 9601 } 9602 9603 /*@ 9604 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9605 9606 Not Collective 9607 9608 Input Parameter: 9609 . A - the matrix to check 9610 9611 Output Parameters: 9612 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9613 - flg - the result (only valid if set is `PETSC_TRUE`) 9614 9615 Level: advanced 9616 9617 Notes: 9618 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9619 if you want it explicitly checked 9620 9621 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9622 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9623 9624 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9625 @*/ 9626 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9627 { 9628 PetscFunctionBegin; 9629 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9630 PetscAssertPointer(set, 2); 9631 PetscAssertPointer(flg, 3); 9632 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9633 *set = PETSC_TRUE; 9634 *flg = PetscBool3ToBool(A->hermitian); 9635 } else { 9636 *set = PETSC_FALSE; 9637 } 9638 PetscFunctionReturn(PETSC_SUCCESS); 9639 } 9640 9641 /*@ 9642 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9643 9644 Collective 9645 9646 Input Parameter: 9647 . A - the matrix to test 9648 9649 Output Parameter: 9650 . flg - the result 9651 9652 Level: intermediate 9653 9654 Notes: 9655 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9656 9657 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 9658 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9659 9660 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9661 @*/ 9662 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9663 { 9664 PetscFunctionBegin; 9665 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9666 PetscAssertPointer(flg, 2); 9667 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9668 *flg = PetscBool3ToBool(A->structurally_symmetric); 9669 } else { 9670 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9671 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9672 } 9673 PetscFunctionReturn(PETSC_SUCCESS); 9674 } 9675 9676 /*@ 9677 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9678 9679 Not Collective 9680 9681 Input Parameter: 9682 . A - the matrix to check 9683 9684 Output Parameters: 9685 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9686 - flg - the result (only valid if set is PETSC_TRUE) 9687 9688 Level: advanced 9689 9690 Notes: 9691 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 9692 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9693 9694 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9695 9696 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9697 @*/ 9698 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9699 { 9700 PetscFunctionBegin; 9701 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9702 PetscAssertPointer(set, 2); 9703 PetscAssertPointer(flg, 3); 9704 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9705 *set = PETSC_TRUE; 9706 *flg = PetscBool3ToBool(A->structurally_symmetric); 9707 } else { 9708 *set = PETSC_FALSE; 9709 } 9710 PetscFunctionReturn(PETSC_SUCCESS); 9711 } 9712 9713 /*@ 9714 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9715 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9716 9717 Not Collective 9718 9719 Input Parameter: 9720 . mat - the matrix 9721 9722 Output Parameters: 9723 + nstash - the size of the stash 9724 . reallocs - the number of additional mallocs incurred. 9725 . bnstash - the size of the block stash 9726 - breallocs - the number of additional mallocs incurred.in the block stash 9727 9728 Level: advanced 9729 9730 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9731 @*/ 9732 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9733 { 9734 PetscFunctionBegin; 9735 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9736 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9737 PetscFunctionReturn(PETSC_SUCCESS); 9738 } 9739 9740 /*@ 9741 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9742 parallel layout, `PetscLayout` for rows and columns 9743 9744 Collective 9745 9746 Input Parameter: 9747 . mat - the matrix 9748 9749 Output Parameters: 9750 + right - (optional) vector that the matrix can be multiplied against 9751 - left - (optional) vector that the matrix vector product can be stored in 9752 9753 Level: advanced 9754 9755 Notes: 9756 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()`. 9757 9758 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9759 9760 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9761 @*/ 9762 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9763 { 9764 PetscFunctionBegin; 9765 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9766 PetscValidType(mat, 1); 9767 if (mat->ops->getvecs) { 9768 PetscUseTypeMethod(mat, getvecs, right, left); 9769 } else { 9770 if (right) { 9771 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9772 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9773 PetscCall(VecSetType(*right, mat->defaultvectype)); 9774 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9775 if (mat->boundtocpu && mat->bindingpropagates) { 9776 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9777 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9778 } 9779 #endif 9780 } 9781 if (left) { 9782 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9783 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9784 PetscCall(VecSetType(*left, mat->defaultvectype)); 9785 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9786 if (mat->boundtocpu && mat->bindingpropagates) { 9787 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9788 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9789 } 9790 #endif 9791 } 9792 } 9793 PetscFunctionReturn(PETSC_SUCCESS); 9794 } 9795 9796 /*@ 9797 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9798 with default values. 9799 9800 Not Collective 9801 9802 Input Parameter: 9803 . info - the `MatFactorInfo` data structure 9804 9805 Level: developer 9806 9807 Notes: 9808 The solvers are generally used through the `KSP` and `PC` objects, for example 9809 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9810 9811 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9812 9813 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9814 @*/ 9815 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9816 { 9817 PetscFunctionBegin; 9818 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9819 PetscFunctionReturn(PETSC_SUCCESS); 9820 } 9821 9822 /*@ 9823 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9824 9825 Collective 9826 9827 Input Parameters: 9828 + mat - the factored matrix 9829 - is - the index set defining the Schur indices (0-based) 9830 9831 Level: advanced 9832 9833 Notes: 9834 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9835 9836 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9837 9838 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9839 9840 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9841 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9842 @*/ 9843 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9844 { 9845 PetscErrorCode (*f)(Mat, IS); 9846 9847 PetscFunctionBegin; 9848 PetscValidType(mat, 1); 9849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9850 PetscValidType(is, 2); 9851 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9852 PetscCheckSameComm(mat, 1, is, 2); 9853 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9854 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9855 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9856 PetscCall(MatDestroy(&mat->schur)); 9857 PetscCall((*f)(mat, is)); 9858 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9859 PetscFunctionReturn(PETSC_SUCCESS); 9860 } 9861 9862 /*@ 9863 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9864 9865 Logically Collective 9866 9867 Input Parameters: 9868 + F - the factored matrix obtained by calling `MatGetFactor()` 9869 . S - location where to return the Schur complement, can be `NULL` 9870 - status - the status of the Schur complement matrix, can be `NULL` 9871 9872 Level: advanced 9873 9874 Notes: 9875 You must call `MatFactorSetSchurIS()` before calling this routine. 9876 9877 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9878 9879 The routine provides a copy of the Schur matrix stored within the solver data structures. 9880 The caller must destroy the object when it is no longer needed. 9881 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9882 9883 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) 9884 9885 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9886 9887 Developer Note: 9888 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9889 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9890 9891 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9892 @*/ 9893 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9894 { 9895 PetscFunctionBegin; 9896 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9897 if (S) PetscAssertPointer(S, 2); 9898 if (status) PetscAssertPointer(status, 3); 9899 if (S) { 9900 PetscErrorCode (*f)(Mat, Mat *); 9901 9902 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9903 if (f) { 9904 PetscCall((*f)(F, S)); 9905 } else { 9906 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9907 } 9908 } 9909 if (status) *status = F->schur_status; 9910 PetscFunctionReturn(PETSC_SUCCESS); 9911 } 9912 9913 /*@ 9914 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9915 9916 Logically Collective 9917 9918 Input Parameters: 9919 + F - the factored matrix obtained by calling `MatGetFactor()` 9920 . S - location where to return the Schur complement, can be `NULL` 9921 - status - the status of the Schur complement matrix, can be `NULL` 9922 9923 Level: advanced 9924 9925 Notes: 9926 You must call `MatFactorSetSchurIS()` before calling this routine. 9927 9928 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9929 9930 The routine returns a the Schur Complement stored within the data structures of the solver. 9931 9932 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9933 9934 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9935 9936 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9937 9938 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9939 9940 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9941 @*/ 9942 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9943 { 9944 PetscFunctionBegin; 9945 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9946 if (S) { 9947 PetscAssertPointer(S, 2); 9948 *S = F->schur; 9949 } 9950 if (status) { 9951 PetscAssertPointer(status, 3); 9952 *status = F->schur_status; 9953 } 9954 PetscFunctionReturn(PETSC_SUCCESS); 9955 } 9956 9957 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9958 { 9959 Mat S = F->schur; 9960 9961 PetscFunctionBegin; 9962 switch (F->schur_status) { 9963 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9964 case MAT_FACTOR_SCHUR_INVERTED: 9965 if (S) { 9966 S->ops->solve = NULL; 9967 S->ops->matsolve = NULL; 9968 S->ops->solvetranspose = NULL; 9969 S->ops->matsolvetranspose = NULL; 9970 S->ops->solveadd = NULL; 9971 S->ops->solvetransposeadd = NULL; 9972 S->factortype = MAT_FACTOR_NONE; 9973 PetscCall(PetscFree(S->solvertype)); 9974 } 9975 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9976 break; 9977 default: 9978 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9979 } 9980 PetscFunctionReturn(PETSC_SUCCESS); 9981 } 9982 9983 /*@ 9984 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9985 9986 Logically Collective 9987 9988 Input Parameters: 9989 + F - the factored matrix obtained by calling `MatGetFactor()` 9990 . S - location where the Schur complement is stored 9991 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9992 9993 Level: advanced 9994 9995 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9996 @*/ 9997 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9998 { 9999 PetscFunctionBegin; 10000 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10001 if (S) { 10002 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 10003 *S = NULL; 10004 } 10005 F->schur_status = status; 10006 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 10007 PetscFunctionReturn(PETSC_SUCCESS); 10008 } 10009 10010 /*@ 10011 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 10012 10013 Logically Collective 10014 10015 Input Parameters: 10016 + F - the factored matrix obtained by calling `MatGetFactor()` 10017 . rhs - location where the right-hand side of the Schur complement system is stored 10018 - sol - location where the solution of the Schur complement system has to be returned 10019 10020 Level: advanced 10021 10022 Notes: 10023 The sizes of the vectors should match the size of the Schur complement 10024 10025 Must be called after `MatFactorSetSchurIS()` 10026 10027 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 10028 @*/ 10029 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 10030 { 10031 PetscFunctionBegin; 10032 PetscValidType(F, 1); 10033 PetscValidType(rhs, 2); 10034 PetscValidType(sol, 3); 10035 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10036 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10037 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10038 PetscCheckSameComm(F, 1, rhs, 2); 10039 PetscCheckSameComm(F, 1, sol, 3); 10040 PetscCall(MatFactorFactorizeSchurComplement(F)); 10041 switch (F->schur_status) { 10042 case MAT_FACTOR_SCHUR_FACTORED: 10043 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 10044 break; 10045 case MAT_FACTOR_SCHUR_INVERTED: 10046 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 10047 break; 10048 default: 10049 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10050 } 10051 PetscFunctionReturn(PETSC_SUCCESS); 10052 } 10053 10054 /*@ 10055 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 10056 10057 Logically Collective 10058 10059 Input Parameters: 10060 + F - the factored matrix obtained by calling `MatGetFactor()` 10061 . rhs - location where the right-hand side of the Schur complement system is stored 10062 - sol - location where the solution of the Schur complement system has to be returned 10063 10064 Level: advanced 10065 10066 Notes: 10067 The sizes of the vectors should match the size of the Schur complement 10068 10069 Must be called after `MatFactorSetSchurIS()` 10070 10071 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10072 @*/ 10073 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10074 { 10075 PetscFunctionBegin; 10076 PetscValidType(F, 1); 10077 PetscValidType(rhs, 2); 10078 PetscValidType(sol, 3); 10079 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10080 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10081 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10082 PetscCheckSameComm(F, 1, rhs, 2); 10083 PetscCheckSameComm(F, 1, sol, 3); 10084 PetscCall(MatFactorFactorizeSchurComplement(F)); 10085 switch (F->schur_status) { 10086 case MAT_FACTOR_SCHUR_FACTORED: 10087 PetscCall(MatSolve(F->schur, rhs, sol)); 10088 break; 10089 case MAT_FACTOR_SCHUR_INVERTED: 10090 PetscCall(MatMult(F->schur, rhs, sol)); 10091 break; 10092 default: 10093 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10094 } 10095 PetscFunctionReturn(PETSC_SUCCESS); 10096 } 10097 10098 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10099 #if PetscDefined(HAVE_CUDA) 10100 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10101 #endif 10102 10103 /* Schur status updated in the interface */ 10104 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10105 { 10106 Mat S = F->schur; 10107 10108 PetscFunctionBegin; 10109 if (S) { 10110 PetscMPIInt size; 10111 PetscBool isdense, isdensecuda; 10112 10113 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10114 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10115 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10116 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10117 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10118 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10119 if (isdense) { 10120 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10121 } else if (isdensecuda) { 10122 #if defined(PETSC_HAVE_CUDA) 10123 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10124 #endif 10125 } 10126 // HIP?????????????? 10127 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10128 } 10129 PetscFunctionReturn(PETSC_SUCCESS); 10130 } 10131 10132 /*@ 10133 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10134 10135 Logically Collective 10136 10137 Input Parameter: 10138 . F - the factored matrix obtained by calling `MatGetFactor()` 10139 10140 Level: advanced 10141 10142 Notes: 10143 Must be called after `MatFactorSetSchurIS()`. 10144 10145 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10146 10147 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10148 @*/ 10149 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10150 { 10151 PetscFunctionBegin; 10152 PetscValidType(F, 1); 10153 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10154 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10155 PetscCall(MatFactorFactorizeSchurComplement(F)); 10156 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10157 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10158 PetscFunctionReturn(PETSC_SUCCESS); 10159 } 10160 10161 /*@ 10162 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10163 10164 Logically Collective 10165 10166 Input Parameter: 10167 . F - the factored matrix obtained by calling `MatGetFactor()` 10168 10169 Level: advanced 10170 10171 Note: 10172 Must be called after `MatFactorSetSchurIS()` 10173 10174 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10175 @*/ 10176 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10177 { 10178 MatFactorInfo info; 10179 10180 PetscFunctionBegin; 10181 PetscValidType(F, 1); 10182 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10183 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10184 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10185 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10186 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10187 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10188 } else { 10189 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10190 } 10191 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10192 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10193 PetscFunctionReturn(PETSC_SUCCESS); 10194 } 10195 10196 /*@ 10197 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10198 10199 Neighbor-wise Collective 10200 10201 Input Parameters: 10202 + A - the matrix 10203 . P - the projection matrix 10204 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10205 - 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 10206 if the result is a dense matrix this is irrelevant 10207 10208 Output Parameter: 10209 . C - the product matrix 10210 10211 Level: intermediate 10212 10213 Notes: 10214 C will be created and must be destroyed by the user with `MatDestroy()`. 10215 10216 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10217 10218 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10219 10220 Developer Note: 10221 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10222 10223 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10224 @*/ 10225 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10226 { 10227 PetscFunctionBegin; 10228 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10229 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10230 10231 if (scall == MAT_INITIAL_MATRIX) { 10232 PetscCall(MatProductCreate(A, P, NULL, C)); 10233 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10234 PetscCall(MatProductSetAlgorithm(*C, "default")); 10235 PetscCall(MatProductSetFill(*C, fill)); 10236 10237 (*C)->product->api_user = PETSC_TRUE; 10238 PetscCall(MatProductSetFromOptions(*C)); 10239 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); 10240 PetscCall(MatProductSymbolic(*C)); 10241 } else { /* scall == MAT_REUSE_MATRIX */ 10242 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10243 } 10244 10245 PetscCall(MatProductNumeric(*C)); 10246 (*C)->symmetric = A->symmetric; 10247 (*C)->spd = A->spd; 10248 PetscFunctionReturn(PETSC_SUCCESS); 10249 } 10250 10251 /*@ 10252 MatRARt - Creates the matrix product $C = R * A * R^T$ 10253 10254 Neighbor-wise Collective 10255 10256 Input Parameters: 10257 + A - the matrix 10258 . R - the projection matrix 10259 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10260 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10261 if the result is a dense matrix this is irrelevant 10262 10263 Output Parameter: 10264 . C - the product matrix 10265 10266 Level: intermediate 10267 10268 Notes: 10269 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10270 10271 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10272 10273 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10274 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10275 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10276 We recommend using `MatPtAP()` when possible. 10277 10278 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10279 10280 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10281 @*/ 10282 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10283 { 10284 PetscFunctionBegin; 10285 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10286 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10287 10288 if (scall == MAT_INITIAL_MATRIX) { 10289 PetscCall(MatProductCreate(A, R, NULL, C)); 10290 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10291 PetscCall(MatProductSetAlgorithm(*C, "default")); 10292 PetscCall(MatProductSetFill(*C, fill)); 10293 10294 (*C)->product->api_user = PETSC_TRUE; 10295 PetscCall(MatProductSetFromOptions(*C)); 10296 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); 10297 PetscCall(MatProductSymbolic(*C)); 10298 } else { /* scall == MAT_REUSE_MATRIX */ 10299 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10300 } 10301 10302 PetscCall(MatProductNumeric(*C)); 10303 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10304 PetscFunctionReturn(PETSC_SUCCESS); 10305 } 10306 10307 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10308 { 10309 PetscBool flg = PETSC_TRUE; 10310 10311 PetscFunctionBegin; 10312 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10313 if (scall == MAT_INITIAL_MATRIX) { 10314 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10315 PetscCall(MatProductCreate(A, B, NULL, C)); 10316 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10317 PetscCall(MatProductSetFill(*C, fill)); 10318 } else { /* scall == MAT_REUSE_MATRIX */ 10319 Mat_Product *product = (*C)->product; 10320 10321 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10322 if (flg && product && product->type != ptype) { 10323 PetscCall(MatProductClear(*C)); 10324 product = NULL; 10325 } 10326 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10327 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10328 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10329 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10330 product = (*C)->product; 10331 product->fill = fill; 10332 product->clear = PETSC_TRUE; 10333 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10334 flg = PETSC_FALSE; 10335 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10336 } 10337 } 10338 if (flg) { 10339 (*C)->product->api_user = PETSC_TRUE; 10340 PetscCall(MatProductSetType(*C, ptype)); 10341 PetscCall(MatProductSetFromOptions(*C)); 10342 PetscCall(MatProductSymbolic(*C)); 10343 } 10344 PetscCall(MatProductNumeric(*C)); 10345 PetscFunctionReturn(PETSC_SUCCESS); 10346 } 10347 10348 /*@ 10349 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10350 10351 Neighbor-wise Collective 10352 10353 Input Parameters: 10354 + A - the left matrix 10355 . B - the right matrix 10356 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10357 - 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 10358 if the result is a dense matrix this is irrelevant 10359 10360 Output Parameter: 10361 . C - the product matrix 10362 10363 Notes: 10364 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10365 10366 `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 10367 call to this function with `MAT_INITIAL_MATRIX`. 10368 10369 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10370 10371 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`, 10372 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10373 10374 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10375 10376 Example of Usage: 10377 .vb 10378 MatProductCreate(A,B,NULL,&C); 10379 MatProductSetType(C,MATPRODUCT_AB); 10380 MatProductSymbolic(C); 10381 MatProductNumeric(C); // compute C=A * B 10382 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10383 MatProductNumeric(C); 10384 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10385 MatProductNumeric(C); 10386 .ve 10387 10388 Level: intermediate 10389 10390 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10391 @*/ 10392 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10393 { 10394 PetscFunctionBegin; 10395 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10396 PetscFunctionReturn(PETSC_SUCCESS); 10397 } 10398 10399 /*@ 10400 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10401 10402 Neighbor-wise Collective 10403 10404 Input Parameters: 10405 + A - the left matrix 10406 . B - the right matrix 10407 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10408 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10409 10410 Output Parameter: 10411 . C - the product matrix 10412 10413 Options Database Key: 10414 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10415 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10416 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10417 10418 Level: intermediate 10419 10420 Notes: 10421 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10422 10423 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10424 10425 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10426 actually needed. 10427 10428 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10429 and for pairs of `MATMPIDENSE` matrices. 10430 10431 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10432 10433 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10434 10435 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10436 @*/ 10437 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10438 { 10439 PetscFunctionBegin; 10440 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10441 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10442 PetscFunctionReturn(PETSC_SUCCESS); 10443 } 10444 10445 /*@ 10446 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10447 10448 Neighbor-wise Collective 10449 10450 Input Parameters: 10451 + A - the left matrix 10452 . B - the right matrix 10453 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10454 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10455 10456 Output Parameter: 10457 . C - the product matrix 10458 10459 Level: intermediate 10460 10461 Notes: 10462 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10463 10464 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10465 10466 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10467 10468 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10469 actually needed. 10470 10471 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10472 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10473 10474 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10475 10476 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10477 @*/ 10478 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10479 { 10480 PetscFunctionBegin; 10481 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10482 PetscFunctionReturn(PETSC_SUCCESS); 10483 } 10484 10485 /*@ 10486 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10487 10488 Neighbor-wise Collective 10489 10490 Input Parameters: 10491 + A - the left matrix 10492 . B - the middle matrix 10493 . C - the right matrix 10494 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10495 - 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 10496 if the result is a dense matrix this is irrelevant 10497 10498 Output Parameter: 10499 . D - the product matrix 10500 10501 Level: intermediate 10502 10503 Notes: 10504 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10505 10506 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10507 10508 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10509 10510 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10511 actually needed. 10512 10513 If you have many matrices with the same non-zero structure to multiply, you 10514 should use `MAT_REUSE_MATRIX` in all calls but the first 10515 10516 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10517 10518 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10519 @*/ 10520 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10521 { 10522 PetscFunctionBegin; 10523 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10524 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10525 10526 if (scall == MAT_INITIAL_MATRIX) { 10527 PetscCall(MatProductCreate(A, B, C, D)); 10528 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10529 PetscCall(MatProductSetAlgorithm(*D, "default")); 10530 PetscCall(MatProductSetFill(*D, fill)); 10531 10532 (*D)->product->api_user = PETSC_TRUE; 10533 PetscCall(MatProductSetFromOptions(*D)); 10534 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, 10535 ((PetscObject)C)->type_name); 10536 PetscCall(MatProductSymbolic(*D)); 10537 } else { /* user may change input matrices when REUSE */ 10538 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10539 } 10540 PetscCall(MatProductNumeric(*D)); 10541 PetscFunctionReturn(PETSC_SUCCESS); 10542 } 10543 10544 /*@ 10545 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10546 10547 Collective 10548 10549 Input Parameters: 10550 + mat - the matrix 10551 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10552 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10553 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10554 10555 Output Parameter: 10556 . matredundant - redundant matrix 10557 10558 Level: advanced 10559 10560 Notes: 10561 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10562 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10563 10564 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10565 calling it. 10566 10567 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10568 10569 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10570 @*/ 10571 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10572 { 10573 MPI_Comm comm; 10574 PetscMPIInt size; 10575 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10576 Mat_Redundant *redund = NULL; 10577 PetscSubcomm psubcomm = NULL; 10578 MPI_Comm subcomm_in = subcomm; 10579 Mat *matseq; 10580 IS isrow, iscol; 10581 PetscBool newsubcomm = PETSC_FALSE; 10582 10583 PetscFunctionBegin; 10584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10585 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10586 PetscAssertPointer(*matredundant, 5); 10587 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10588 } 10589 10590 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10591 if (size == 1 || nsubcomm == 1) { 10592 if (reuse == MAT_INITIAL_MATRIX) { 10593 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10594 } else { 10595 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"); 10596 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10597 } 10598 PetscFunctionReturn(PETSC_SUCCESS); 10599 } 10600 10601 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10602 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10603 MatCheckPreallocated(mat, 1); 10604 10605 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10606 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10607 /* create psubcomm, then get subcomm */ 10608 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10609 PetscCallMPI(MPI_Comm_size(comm, &size)); 10610 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10611 10612 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10613 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10614 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10615 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10616 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10617 newsubcomm = PETSC_TRUE; 10618 PetscCall(PetscSubcommDestroy(&psubcomm)); 10619 } 10620 10621 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10622 if (reuse == MAT_INITIAL_MATRIX) { 10623 mloc_sub = PETSC_DECIDE; 10624 nloc_sub = PETSC_DECIDE; 10625 if (bs < 1) { 10626 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10627 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10628 } else { 10629 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10630 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10631 } 10632 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10633 rstart = rend - mloc_sub; 10634 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10635 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10636 PetscCall(ISSetIdentity(iscol)); 10637 } else { /* reuse == MAT_REUSE_MATRIX */ 10638 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"); 10639 /* retrieve subcomm */ 10640 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10641 redund = (*matredundant)->redundant; 10642 isrow = redund->isrow; 10643 iscol = redund->iscol; 10644 matseq = redund->matseq; 10645 } 10646 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10647 10648 /* get matredundant over subcomm */ 10649 if (reuse == MAT_INITIAL_MATRIX) { 10650 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10651 10652 /* create a supporting struct and attach it to C for reuse */ 10653 PetscCall(PetscNew(&redund)); 10654 (*matredundant)->redundant = redund; 10655 redund->isrow = isrow; 10656 redund->iscol = iscol; 10657 redund->matseq = matseq; 10658 if (newsubcomm) { 10659 redund->subcomm = subcomm; 10660 } else { 10661 redund->subcomm = MPI_COMM_NULL; 10662 } 10663 } else { 10664 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10665 } 10666 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10667 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10668 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10669 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10670 } 10671 #endif 10672 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10673 PetscFunctionReturn(PETSC_SUCCESS); 10674 } 10675 10676 /*@C 10677 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10678 a given `Mat`. Each submatrix can span multiple procs. 10679 10680 Collective 10681 10682 Input Parameters: 10683 + mat - the matrix 10684 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10685 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10686 10687 Output Parameter: 10688 . subMat - parallel sub-matrices each spanning a given `subcomm` 10689 10690 Level: advanced 10691 10692 Notes: 10693 The submatrix partition across processors is dictated by `subComm` a 10694 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10695 is not restricted to be grouped with consecutive original MPI processes. 10696 10697 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10698 map directly to the layout of the original matrix [wrt the local 10699 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10700 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10701 the `subMat`. However the offDiagMat looses some columns - and this is 10702 reconstructed with `MatSetValues()` 10703 10704 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10705 10706 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10707 @*/ 10708 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10709 { 10710 PetscMPIInt commsize, subCommSize; 10711 10712 PetscFunctionBegin; 10713 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10714 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10715 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10716 10717 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"); 10718 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10719 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10720 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10721 PetscFunctionReturn(PETSC_SUCCESS); 10722 } 10723 10724 /*@ 10725 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10726 10727 Not Collective 10728 10729 Input Parameters: 10730 + mat - matrix to extract local submatrix from 10731 . isrow - local row indices for submatrix 10732 - iscol - local column indices for submatrix 10733 10734 Output Parameter: 10735 . submat - the submatrix 10736 10737 Level: intermediate 10738 10739 Notes: 10740 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10741 10742 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10743 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10744 10745 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10746 `MatSetValuesBlockedLocal()` will also be implemented. 10747 10748 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10749 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10750 10751 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10752 @*/ 10753 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10754 { 10755 PetscFunctionBegin; 10756 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10757 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10758 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10759 PetscCheckSameComm(isrow, 2, iscol, 3); 10760 PetscAssertPointer(submat, 4); 10761 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10762 10763 if (mat->ops->getlocalsubmatrix) { 10764 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10765 } else { 10766 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10767 } 10768 PetscFunctionReturn(PETSC_SUCCESS); 10769 } 10770 10771 /*@ 10772 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10773 10774 Not Collective 10775 10776 Input Parameters: 10777 + mat - matrix to extract local submatrix from 10778 . isrow - local row indices for submatrix 10779 . iscol - local column indices for submatrix 10780 - submat - the submatrix 10781 10782 Level: intermediate 10783 10784 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10785 @*/ 10786 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10787 { 10788 PetscFunctionBegin; 10789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10790 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10791 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10792 PetscCheckSameComm(isrow, 2, iscol, 3); 10793 PetscAssertPointer(submat, 4); 10794 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10795 10796 if (mat->ops->restorelocalsubmatrix) { 10797 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10798 } else { 10799 PetscCall(MatDestroy(submat)); 10800 } 10801 *submat = NULL; 10802 PetscFunctionReturn(PETSC_SUCCESS); 10803 } 10804 10805 /*@ 10806 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10807 10808 Collective 10809 10810 Input Parameter: 10811 . mat - the matrix 10812 10813 Output Parameter: 10814 . is - if any rows have zero diagonals this contains the list of them 10815 10816 Level: developer 10817 10818 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10819 @*/ 10820 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10821 { 10822 PetscFunctionBegin; 10823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10824 PetscValidType(mat, 1); 10825 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10826 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10827 10828 if (!mat->ops->findzerodiagonals) { 10829 Vec diag; 10830 const PetscScalar *a; 10831 PetscInt *rows; 10832 PetscInt rStart, rEnd, r, nrow = 0; 10833 10834 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10835 PetscCall(MatGetDiagonal(mat, diag)); 10836 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10837 PetscCall(VecGetArrayRead(diag, &a)); 10838 for (r = 0; r < rEnd - rStart; ++r) 10839 if (a[r] == 0.0) ++nrow; 10840 PetscCall(PetscMalloc1(nrow, &rows)); 10841 nrow = 0; 10842 for (r = 0; r < rEnd - rStart; ++r) 10843 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10844 PetscCall(VecRestoreArrayRead(diag, &a)); 10845 PetscCall(VecDestroy(&diag)); 10846 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10847 } else { 10848 PetscUseTypeMethod(mat, findzerodiagonals, is); 10849 } 10850 PetscFunctionReturn(PETSC_SUCCESS); 10851 } 10852 10853 /*@ 10854 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10855 10856 Collective 10857 10858 Input Parameter: 10859 . mat - the matrix 10860 10861 Output Parameter: 10862 . is - contains the list of rows with off block diagonal entries 10863 10864 Level: developer 10865 10866 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10867 @*/ 10868 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10869 { 10870 PetscFunctionBegin; 10871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10872 PetscValidType(mat, 1); 10873 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10874 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10875 10876 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10877 PetscFunctionReturn(PETSC_SUCCESS); 10878 } 10879 10880 /*@C 10881 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10882 10883 Collective; No Fortran Support 10884 10885 Input Parameter: 10886 . mat - the matrix 10887 10888 Output Parameter: 10889 . values - the block inverses in column major order (FORTRAN-like) 10890 10891 Level: advanced 10892 10893 Notes: 10894 The size of the blocks is determined by the block size of the matrix. 10895 10896 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10897 10898 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10899 10900 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10901 @*/ 10902 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10903 { 10904 PetscFunctionBegin; 10905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10906 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10907 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10908 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10909 PetscFunctionReturn(PETSC_SUCCESS); 10910 } 10911 10912 /*@ 10913 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10914 10915 Collective; No Fortran Support 10916 10917 Input Parameters: 10918 + mat - the matrix 10919 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10920 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10921 10922 Output Parameter: 10923 . values - the block inverses in column major order (FORTRAN-like) 10924 10925 Level: advanced 10926 10927 Notes: 10928 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10929 10930 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10931 10932 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10933 @*/ 10934 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10935 { 10936 PetscFunctionBegin; 10937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10938 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10939 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10940 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10941 PetscFunctionReturn(PETSC_SUCCESS); 10942 } 10943 10944 /*@ 10945 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10946 10947 Collective 10948 10949 Input Parameters: 10950 + A - the matrix 10951 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10952 10953 Level: advanced 10954 10955 Note: 10956 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10957 10958 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10959 @*/ 10960 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10961 { 10962 const PetscScalar *vals; 10963 PetscInt *dnnz; 10964 PetscInt m, rstart, rend, bs, i, j; 10965 10966 PetscFunctionBegin; 10967 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10968 PetscCall(MatGetBlockSize(A, &bs)); 10969 PetscCall(MatGetLocalSize(A, &m, NULL)); 10970 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10971 if (A->rmap->bs > 1) PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); // mpiaij to A and B 10972 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10973 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10974 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10975 PetscCall(PetscFree(dnnz)); 10976 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10977 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10978 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10979 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10980 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10981 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10982 PetscFunctionReturn(PETSC_SUCCESS); 10983 } 10984 10985 /*@ 10986 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10987 via `MatTransposeColoringCreate()`. 10988 10989 Collective 10990 10991 Input Parameter: 10992 . c - coloring context 10993 10994 Level: intermediate 10995 10996 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10997 @*/ 10998 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10999 { 11000 MatTransposeColoring matcolor = *c; 11001 11002 PetscFunctionBegin; 11003 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 11004 if (--((PetscObject)matcolor)->refct > 0) { 11005 matcolor = NULL; 11006 PetscFunctionReturn(PETSC_SUCCESS); 11007 } 11008 11009 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 11010 PetscCall(PetscFree(matcolor->rows)); 11011 PetscCall(PetscFree(matcolor->den2sp)); 11012 PetscCall(PetscFree(matcolor->colorforcol)); 11013 PetscCall(PetscFree(matcolor->columns)); 11014 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 11015 PetscCall(PetscHeaderDestroy(c)); 11016 PetscFunctionReturn(PETSC_SUCCESS); 11017 } 11018 11019 /*@ 11020 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 11021 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 11022 `MatTransposeColoring` to sparse `B`. 11023 11024 Collective 11025 11026 Input Parameters: 11027 + coloring - coloring context created with `MatTransposeColoringCreate()` 11028 - B - sparse matrix 11029 11030 Output Parameter: 11031 . Btdense - dense matrix $B^T$ 11032 11033 Level: developer 11034 11035 Note: 11036 These are used internally for some implementations of `MatRARt()` 11037 11038 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 11039 @*/ 11040 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 11041 { 11042 PetscFunctionBegin; 11043 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11044 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 11045 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 11046 11047 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 11048 PetscFunctionReturn(PETSC_SUCCESS); 11049 } 11050 11051 /*@ 11052 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 11053 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 11054 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 11055 $C_{sp}$ from $C_{den}$. 11056 11057 Collective 11058 11059 Input Parameters: 11060 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 11061 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 11062 11063 Output Parameter: 11064 . Csp - sparse matrix 11065 11066 Level: developer 11067 11068 Note: 11069 These are used internally for some implementations of `MatRARt()` 11070 11071 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11072 @*/ 11073 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11074 { 11075 PetscFunctionBegin; 11076 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11077 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11078 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11079 11080 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11081 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11082 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11083 PetscFunctionReturn(PETSC_SUCCESS); 11084 } 11085 11086 /*@ 11087 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11088 11089 Collective 11090 11091 Input Parameters: 11092 + mat - the matrix product C 11093 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11094 11095 Output Parameter: 11096 . color - the new coloring context 11097 11098 Level: intermediate 11099 11100 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11101 `MatTransColoringApplyDenToSp()` 11102 @*/ 11103 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11104 { 11105 MatTransposeColoring c; 11106 MPI_Comm comm; 11107 11108 PetscFunctionBegin; 11109 PetscAssertPointer(color, 3); 11110 11111 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11112 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11113 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11114 c->ctype = iscoloring->ctype; 11115 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11116 *color = c; 11117 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11118 PetscFunctionReturn(PETSC_SUCCESS); 11119 } 11120 11121 /*@ 11122 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11123 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11124 11125 Not Collective 11126 11127 Input Parameter: 11128 . mat - the matrix 11129 11130 Output Parameter: 11131 . state - the current state 11132 11133 Level: intermediate 11134 11135 Notes: 11136 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11137 different matrices 11138 11139 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11140 11141 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11142 11143 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11144 @*/ 11145 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11146 { 11147 PetscFunctionBegin; 11148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11149 *state = mat->nonzerostate; 11150 PetscFunctionReturn(PETSC_SUCCESS); 11151 } 11152 11153 /*@ 11154 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11155 matrices from each processor 11156 11157 Collective 11158 11159 Input Parameters: 11160 + comm - the communicators the parallel matrix will live on 11161 . seqmat - the input sequential matrices 11162 . n - number of local columns (or `PETSC_DECIDE`) 11163 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11164 11165 Output Parameter: 11166 . mpimat - the parallel matrix generated 11167 11168 Level: developer 11169 11170 Note: 11171 The number of columns of the matrix in EACH processor MUST be the same. 11172 11173 .seealso: [](ch_matrices), `Mat` 11174 @*/ 11175 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11176 { 11177 PetscMPIInt size; 11178 11179 PetscFunctionBegin; 11180 PetscCallMPI(MPI_Comm_size(comm, &size)); 11181 if (size == 1) { 11182 if (reuse == MAT_INITIAL_MATRIX) { 11183 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11184 } else { 11185 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11186 } 11187 PetscFunctionReturn(PETSC_SUCCESS); 11188 } 11189 11190 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"); 11191 11192 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11193 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11194 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11195 PetscFunctionReturn(PETSC_SUCCESS); 11196 } 11197 11198 /*@ 11199 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11200 11201 Collective 11202 11203 Input Parameters: 11204 + A - the matrix to create subdomains from 11205 - N - requested number of subdomains 11206 11207 Output Parameters: 11208 + n - number of subdomains resulting on this MPI process 11209 - iss - `IS` list with indices of subdomains on this MPI process 11210 11211 Level: advanced 11212 11213 Note: 11214 The number of subdomains must be smaller than the communicator size 11215 11216 .seealso: [](ch_matrices), `Mat`, `IS` 11217 @*/ 11218 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11219 { 11220 MPI_Comm comm, subcomm; 11221 PetscMPIInt size, rank, color; 11222 PetscInt rstart, rend, k; 11223 11224 PetscFunctionBegin; 11225 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11226 PetscCallMPI(MPI_Comm_size(comm, &size)); 11227 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11228 PetscCheck(N >= 1 && N < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N); 11229 *n = 1; 11230 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11231 color = rank / k; 11232 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11233 PetscCall(PetscMalloc1(1, iss)); 11234 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11235 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11236 PetscCallMPI(MPI_Comm_free(&subcomm)); 11237 PetscFunctionReturn(PETSC_SUCCESS); 11238 } 11239 11240 /*@ 11241 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11242 11243 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11244 If they are not the same, uses `MatMatMatMult()`. 11245 11246 Once the coarse grid problem is constructed, correct for interpolation operators 11247 that are not of full rank, which can legitimately happen in the case of non-nested 11248 geometric multigrid. 11249 11250 Input Parameters: 11251 + restrct - restriction operator 11252 . dA - fine grid matrix 11253 . interpolate - interpolation operator 11254 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11255 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11256 11257 Output Parameter: 11258 . A - the Galerkin coarse matrix 11259 11260 Options Database Key: 11261 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11262 11263 Level: developer 11264 11265 Note: 11266 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11267 11268 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11269 @*/ 11270 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11271 { 11272 IS zerorows; 11273 Vec diag; 11274 11275 PetscFunctionBegin; 11276 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11277 /* Construct the coarse grid matrix */ 11278 if (interpolate == restrct) { 11279 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11280 } else { 11281 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11282 } 11283 11284 /* If the interpolation matrix is not of full rank, A will have zero rows. 11285 This can legitimately happen in the case of non-nested geometric multigrid. 11286 In that event, we set the rows of the matrix to the rows of the identity, 11287 ignoring the equations (as the RHS will also be zero). */ 11288 11289 PetscCall(MatFindZeroRows(*A, &zerorows)); 11290 11291 if (zerorows != NULL) { /* if there are any zero rows */ 11292 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11293 PetscCall(MatGetDiagonal(*A, diag)); 11294 PetscCall(VecISSet(diag, zerorows, 1.0)); 11295 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11296 PetscCall(VecDestroy(&diag)); 11297 PetscCall(ISDestroy(&zerorows)); 11298 } 11299 PetscFunctionReturn(PETSC_SUCCESS); 11300 } 11301 11302 /*@C 11303 MatSetOperation - Allows user to set a matrix operation for any matrix type 11304 11305 Logically Collective 11306 11307 Input Parameters: 11308 + mat - the matrix 11309 . op - the name of the operation 11310 - f - the function that provides the operation 11311 11312 Level: developer 11313 11314 Example Usage: 11315 .vb 11316 extern PetscErrorCode usermult(Mat, Vec, Vec); 11317 11318 PetscCall(MatCreateXXX(comm, ..., &A)); 11319 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11320 .ve 11321 11322 Notes: 11323 See the file `include/petscmat.h` for a complete list of matrix 11324 operations, which all have the form MATOP_<OPERATION>, where 11325 <OPERATION> is the name (in all capital letters) of the 11326 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11327 11328 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11329 sequence as the usual matrix interface routines, since they 11330 are intended to be accessed via the usual matrix interface 11331 routines, e.g., 11332 .vb 11333 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11334 .ve 11335 11336 In particular each function MUST return `PETSC_SUCCESS` on success and 11337 nonzero on failure. 11338 11339 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11340 11341 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11342 @*/ 11343 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11344 { 11345 PetscFunctionBegin; 11346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11347 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11348 (((void (**)(void))mat->ops)[op]) = f; 11349 PetscFunctionReturn(PETSC_SUCCESS); 11350 } 11351 11352 /*@C 11353 MatGetOperation - Gets a matrix operation for any matrix type. 11354 11355 Not Collective 11356 11357 Input Parameters: 11358 + mat - the matrix 11359 - op - the name of the operation 11360 11361 Output Parameter: 11362 . f - the function that provides the operation 11363 11364 Level: developer 11365 11366 Example Usage: 11367 .vb 11368 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11369 11370 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11371 .ve 11372 11373 Notes: 11374 See the file include/petscmat.h for a complete list of matrix 11375 operations, which all have the form MATOP_<OPERATION>, where 11376 <OPERATION> is the name (in all capital letters) of the 11377 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11378 11379 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11380 11381 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11382 @*/ 11383 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11384 { 11385 PetscFunctionBegin; 11386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11387 *f = (((void (**)(void))mat->ops)[op]); 11388 PetscFunctionReturn(PETSC_SUCCESS); 11389 } 11390 11391 /*@ 11392 MatHasOperation - Determines whether the given matrix supports the particular operation. 11393 11394 Not Collective 11395 11396 Input Parameters: 11397 + mat - the matrix 11398 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11399 11400 Output Parameter: 11401 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11402 11403 Level: advanced 11404 11405 Note: 11406 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11407 11408 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11409 @*/ 11410 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11411 { 11412 PetscFunctionBegin; 11413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11414 PetscAssertPointer(has, 3); 11415 if (mat->ops->hasoperation) { 11416 PetscUseTypeMethod(mat, hasoperation, op, has); 11417 } else { 11418 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11419 else { 11420 *has = PETSC_FALSE; 11421 if (op == MATOP_CREATE_SUBMATRIX) { 11422 PetscMPIInt size; 11423 11424 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11425 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11426 } 11427 } 11428 } 11429 PetscFunctionReturn(PETSC_SUCCESS); 11430 } 11431 11432 /*@ 11433 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11434 11435 Collective 11436 11437 Input Parameter: 11438 . mat - the matrix 11439 11440 Output Parameter: 11441 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11442 11443 Level: beginner 11444 11445 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11446 @*/ 11447 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11448 { 11449 PetscFunctionBegin; 11450 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11451 PetscValidType(mat, 1); 11452 PetscAssertPointer(cong, 2); 11453 if (!mat->rmap || !mat->cmap) { 11454 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11455 PetscFunctionReturn(PETSC_SUCCESS); 11456 } 11457 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11458 PetscCall(PetscLayoutSetUp(mat->rmap)); 11459 PetscCall(PetscLayoutSetUp(mat->cmap)); 11460 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11461 if (*cong) mat->congruentlayouts = 1; 11462 else mat->congruentlayouts = 0; 11463 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11464 PetscFunctionReturn(PETSC_SUCCESS); 11465 } 11466 11467 PetscErrorCode MatSetInf(Mat A) 11468 { 11469 PetscFunctionBegin; 11470 PetscUseTypeMethod(A, setinf); 11471 PetscFunctionReturn(PETSC_SUCCESS); 11472 } 11473 11474 /*@ 11475 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 11476 and possibly removes small values from the graph structure. 11477 11478 Collective 11479 11480 Input Parameters: 11481 + A - the matrix 11482 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11483 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11484 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11485 . num_idx - size of 'index' array 11486 - index - array of block indices to use for graph strength of connection weight 11487 11488 Output Parameter: 11489 . graph - the resulting graph 11490 11491 Level: advanced 11492 11493 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11494 @*/ 11495 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11496 { 11497 PetscFunctionBegin; 11498 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11499 PetscValidType(A, 1); 11500 PetscValidLogicalCollectiveBool(A, scale, 3); 11501 PetscAssertPointer(graph, 7); 11502 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11503 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11504 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11505 PetscFunctionReturn(PETSC_SUCCESS); 11506 } 11507 11508 /*@ 11509 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11510 meaning the same memory is used for the matrix, and no new memory is allocated. 11511 11512 Collective 11513 11514 Input Parameters: 11515 + A - the matrix 11516 - 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 11517 11518 Level: intermediate 11519 11520 Developer Note: 11521 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11522 of the arrays in the data structure are unneeded. 11523 11524 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11525 @*/ 11526 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11527 { 11528 PetscFunctionBegin; 11529 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11530 PetscUseTypeMethod(A, eliminatezeros, keep); 11531 PetscFunctionReturn(PETSC_SUCCESS); 11532 } 11533