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 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 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); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 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. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscTryMethod(A, "MatSetOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 759 PetscFunctionReturn(PETSC_SUCCESS); 760 } 761 762 /*@ 763 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 764 for matrices created with `MatGetFactor()` 765 766 Logically Collective 767 768 Input Parameters: 769 + A - the matrix 770 - prefix - the prefix to prepend to all option names for the factored matrix 771 772 Level: developer 773 774 Notes: 775 A hyphen (-) must NOT be given at the beginning of the prefix name. 776 The first character of all runtime options is AUTOMATICALLY the hyphen. 777 778 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 779 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 780 781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 782 @*/ 783 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 784 { 785 PetscFunctionBegin; 786 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 787 if (prefix) { 788 PetscAssertPointer(prefix, 2); 789 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 790 if (prefix != A->factorprefix) { 791 PetscCall(PetscFree(A->factorprefix)); 792 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 793 } 794 } else PetscCall(PetscFree(A->factorprefix)); 795 PetscFunctionReturn(PETSC_SUCCESS); 796 } 797 798 /*@ 799 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 800 for matrices created with `MatGetFactor()` 801 802 Logically Collective 803 804 Input Parameters: 805 + A - the matrix 806 - prefix - the prefix to prepend to all option names for the factored matrix 807 808 Level: developer 809 810 Notes: 811 A hyphen (-) must NOT be given at the beginning of the prefix name. 812 The first character of all runtime options is AUTOMATICALLY the hyphen. 813 814 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 815 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 816 817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 818 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 819 `MatSetOptionsPrefix()` 820 @*/ 821 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 822 { 823 size_t len1, len2, new_len; 824 825 PetscFunctionBegin; 826 PetscValidHeader(A, 1); 827 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 828 if (!A->factorprefix) { 829 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 830 PetscFunctionReturn(PETSC_SUCCESS); 831 } 832 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 833 834 PetscCall(PetscStrlen(A->factorprefix, &len1)); 835 PetscCall(PetscStrlen(prefix, &len2)); 836 new_len = len1 + len2 + 1; 837 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 838 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 839 PetscFunctionReturn(PETSC_SUCCESS); 840 } 841 842 /*@ 843 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 844 matrix options in the database. 845 846 Logically Collective 847 848 Input Parameters: 849 + A - the matrix 850 - prefix - the prefix to prepend to all option names 851 852 Level: advanced 853 854 Note: 855 A hyphen (-) must NOT be given at the beginning of the prefix name. 856 The first character of all runtime options is AUTOMATICALLY the hyphen. 857 858 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 859 @*/ 860 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 861 { 862 PetscFunctionBegin; 863 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 864 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 865 PetscTryMethod(A, "MatAppendOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 866 PetscFunctionReturn(PETSC_SUCCESS); 867 } 868 869 /*@ 870 MatGetOptionsPrefix - Gets the prefix used for searching for all 871 matrix options in the database. 872 873 Not Collective 874 875 Input Parameter: 876 . A - the matrix 877 878 Output Parameter: 879 . prefix - pointer to the prefix string used 880 881 Level: advanced 882 883 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 884 @*/ 885 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 886 { 887 PetscFunctionBegin; 888 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 889 PetscAssertPointer(prefix, 2); 890 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 891 PetscFunctionReturn(PETSC_SUCCESS); 892 } 893 894 /*@ 895 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 896 897 Not Collective 898 899 Input Parameter: 900 . A - the matrix 901 902 Output Parameter: 903 . state - the object state 904 905 Level: advanced 906 907 Note: 908 Object state is an integer which gets increased every time 909 the object is changed. By saving and later querying the object state 910 one can determine whether information about the object is still current. 911 912 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 913 914 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 915 @*/ 916 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 917 { 918 PetscFunctionBegin; 919 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 920 PetscAssertPointer(state, 2); 921 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 922 PetscFunctionReturn(PETSC_SUCCESS); 923 } 924 925 /*@ 926 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 927 928 Collective 929 930 Input Parameter: 931 . A - the matrix 932 933 Level: beginner 934 935 Notes: 936 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 937 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 938 makes all of the preallocation space available 939 940 Current values in the matrix are lost in this call 941 942 Currently only supported for `MATAIJ` matrices. 943 944 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 945 @*/ 946 PetscErrorCode MatResetPreallocation(Mat A) 947 { 948 PetscFunctionBegin; 949 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 950 PetscValidType(A, 1); 951 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 952 PetscFunctionReturn(PETSC_SUCCESS); 953 } 954 955 /*@ 956 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 957 958 Collective 959 960 Input Parameter: 961 . A - the matrix 962 963 Level: intermediate 964 965 Notes: 966 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 967 968 Currently only supported for `MATAIJ` matrices. 969 970 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 971 @*/ 972 PetscErrorCode MatResetHash(Mat A) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscValidType(A, 1); 977 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()"); 978 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 979 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 980 /* These flags are used to determine whether certain setups occur */ 981 A->was_assembled = PETSC_FALSE; 982 A->assembled = PETSC_FALSE; 983 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 984 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 985 PetscFunctionReturn(PETSC_SUCCESS); 986 } 987 988 /*@ 989 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 990 991 Collective 992 993 Input Parameter: 994 . A - the matrix 995 996 Level: advanced 997 998 Notes: 999 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1000 setting values in the matrix. 1001 1002 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1003 1004 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1005 @*/ 1006 PetscErrorCode MatSetUp(Mat A) 1007 { 1008 PetscFunctionBegin; 1009 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1010 if (!((PetscObject)A)->type_name) { 1011 PetscMPIInt size; 1012 1013 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1014 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1015 } 1016 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1017 PetscCall(PetscLayoutSetUp(A->rmap)); 1018 PetscCall(PetscLayoutSetUp(A->cmap)); 1019 A->preallocated = PETSC_TRUE; 1020 PetscFunctionReturn(PETSC_SUCCESS); 1021 } 1022 1023 #if defined(PETSC_HAVE_SAWS) 1024 #include <petscviewersaws.h> 1025 #endif 1026 1027 /* 1028 If threadsafety is on extraneous matrices may be printed 1029 1030 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1031 */ 1032 #if !defined(PETSC_HAVE_THREADSAFETY) 1033 static PetscInt insidematview = 0; 1034 #endif 1035 1036 /*@ 1037 MatViewFromOptions - View properties of the matrix based on options set in the options database 1038 1039 Collective 1040 1041 Input Parameters: 1042 + A - the matrix 1043 . obj - optional additional object that provides the options prefix to use 1044 - name - command line option 1045 1046 Options Database Key: 1047 . -mat_view [viewertype]:... - the viewer and its options 1048 1049 Level: intermediate 1050 1051 Note: 1052 .vb 1053 If no value is provided ascii:stdout is used 1054 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1055 for example ascii::ascii_info prints just the information about the object not all details 1056 unless :append is given filename opens in write mode, overwriting what was already there 1057 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1058 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1059 socket[:port] defaults to the standard output port 1060 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1061 .ve 1062 1063 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1064 @*/ 1065 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1066 { 1067 PetscFunctionBegin; 1068 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1069 #if !defined(PETSC_HAVE_THREADSAFETY) 1070 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1071 #endif 1072 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1073 PetscFunctionReturn(PETSC_SUCCESS); 1074 } 1075 1076 /*@ 1077 MatView - display information about a matrix in a variety ways 1078 1079 Collective on viewer 1080 1081 Input Parameters: 1082 + mat - the matrix 1083 - viewer - visualization context 1084 1085 Options Database Keys: 1086 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1087 . -mat_view ::ascii_info_detail - Prints more detailed info 1088 . -mat_view - Prints matrix in ASCII format 1089 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1090 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1091 . -display <name> - Sets display name (default is host) 1092 . -draw_pause <sec> - Sets number of seconds to pause after display 1093 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1094 . -viewer_socket_machine <machine> - - 1095 . -viewer_socket_port <port> - - 1096 . -mat_view binary - save matrix to file in binary format 1097 - -viewer_binary_filename <name> - - 1098 1099 Level: beginner 1100 1101 Notes: 1102 The available visualization contexts include 1103 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1104 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1105 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1106 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1107 1108 The user can open alternative visualization contexts with 1109 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1110 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1111 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1112 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1113 1114 The user can call `PetscViewerPushFormat()` to specify the output 1115 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1116 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1117 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1118 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1119 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1120 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1121 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1122 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1123 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1124 1125 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1126 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1127 1128 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1129 1130 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1131 viewer is used. 1132 1133 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1134 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1135 1136 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1137 and then use the following mouse functions. 1138 .vb 1139 left mouse: zoom in 1140 middle mouse: zoom out 1141 right mouse: continue with the simulation 1142 .ve 1143 1144 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1145 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1146 @*/ 1147 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1148 { 1149 PetscInt rows, cols, rbs, cbs; 1150 PetscBool isascii, isstring, issaws; 1151 PetscViewerFormat format; 1152 PetscMPIInt size; 1153 1154 PetscFunctionBegin; 1155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1156 PetscValidType(mat, 1); 1157 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1158 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1159 1160 PetscCall(PetscViewerGetFormat(viewer, &format)); 1161 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1162 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1163 1164 #if !defined(PETSC_HAVE_THREADSAFETY) 1165 insidematview++; 1166 #endif 1167 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1168 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1169 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1170 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"); 1171 1172 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1173 if (isascii) { 1174 if (!mat->preallocated) { 1175 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1176 #if !defined(PETSC_HAVE_THREADSAFETY) 1177 insidematview--; 1178 #endif 1179 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1180 PetscFunctionReturn(PETSC_SUCCESS); 1181 } 1182 if (!mat->assembled) { 1183 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled 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 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1191 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1192 MatNullSpace nullsp, transnullsp; 1193 1194 PetscCall(PetscViewerASCIIPushTab(viewer)); 1195 PetscCall(MatGetSize(mat, &rows, &cols)); 1196 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1197 if (rbs != 1 || cbs != 1) { 1198 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" : "")); 1199 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1200 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1201 if (mat->factortype) { 1202 MatSolverType solver; 1203 PetscCall(MatFactorGetSolverType(mat, &solver)); 1204 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1205 } 1206 if (mat->ops->getinfo) { 1207 PetscBool is_constant_or_diagonal; 1208 1209 // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output 1210 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, "")); 1211 if (!is_constant_or_diagonal) { 1212 MatInfo info; 1213 1214 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1215 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1216 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1217 } 1218 } 1219 PetscCall(MatGetNullSpace(mat, &nullsp)); 1220 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1221 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1222 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1223 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1224 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1225 PetscCall(PetscViewerASCIIPushTab(viewer)); 1226 PetscCall(MatProductView(mat, viewer)); 1227 PetscCall(PetscViewerASCIIPopTab(viewer)); 1228 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1229 IS tmp; 1230 1231 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1232 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1233 PetscCall(PetscViewerASCIIPushTab(viewer)); 1234 PetscCall(ISView(tmp, viewer)); 1235 PetscCall(PetscViewerASCIIPopTab(viewer)); 1236 PetscCall(ISDestroy(&tmp)); 1237 } 1238 } 1239 } else if (issaws) { 1240 #if defined(PETSC_HAVE_SAWS) 1241 PetscMPIInt rank; 1242 1243 PetscCall(PetscObjectName((PetscObject)mat)); 1244 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1245 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1246 #endif 1247 } else if (isstring) { 1248 const char *type; 1249 PetscCall(MatGetType(mat, &type)); 1250 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1251 PetscTryTypeMethod(mat, view, viewer); 1252 } 1253 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1254 PetscCall(PetscViewerASCIIPushTab(viewer)); 1255 PetscUseTypeMethod(mat, viewnative, viewer); 1256 PetscCall(PetscViewerASCIIPopTab(viewer)); 1257 } else if (mat->ops->view) { 1258 PetscCall(PetscViewerASCIIPushTab(viewer)); 1259 PetscUseTypeMethod(mat, view, viewer); 1260 PetscCall(PetscViewerASCIIPopTab(viewer)); 1261 } 1262 if (isascii) { 1263 PetscCall(PetscViewerGetFormat(viewer, &format)); 1264 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1265 } 1266 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1267 #if !defined(PETSC_HAVE_THREADSAFETY) 1268 insidematview--; 1269 #endif 1270 PetscFunctionReturn(PETSC_SUCCESS); 1271 } 1272 1273 #if defined(PETSC_USE_DEBUG) 1274 #include <../src/sys/totalview/tv_data_display.h> 1275 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1276 { 1277 TV_add_row("Local rows", "int", &mat->rmap->n); 1278 TV_add_row("Local columns", "int", &mat->cmap->n); 1279 TV_add_row("Global rows", "int", &mat->rmap->N); 1280 TV_add_row("Global columns", "int", &mat->cmap->N); 1281 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1282 return TV_format_OK; 1283 } 1284 #endif 1285 1286 /*@ 1287 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1288 with `MatView()`. The matrix format is determined from the options database. 1289 Generates a parallel MPI matrix if the communicator has more than one 1290 processor. The default matrix type is `MATAIJ`. 1291 1292 Collective 1293 1294 Input Parameters: 1295 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1296 or some related function before a call to `MatLoad()` 1297 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1298 1299 Options Database Key: 1300 . -matload_block_size <bs> - set block size 1301 1302 Level: beginner 1303 1304 Notes: 1305 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1306 `Mat` before calling this routine if you wish to set it from the options database. 1307 1308 `MatLoad()` automatically loads into the options database any options 1309 given in the file filename.info where filename is the name of the file 1310 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1311 file will be ignored if you use the -viewer_binary_skip_info option. 1312 1313 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1314 sets the default matrix type AIJ and sets the local and global sizes. 1315 If type and/or size is already set, then the same are used. 1316 1317 In parallel, each processor can load a subset of rows (or the 1318 entire matrix). This routine is especially useful when a large 1319 matrix is stored on disk and only part of it is desired on each 1320 processor. For example, a parallel solver may access only some of 1321 the rows from each processor. The algorithm used here reads 1322 relatively small blocks of data rather than reading the entire 1323 matrix and then subsetting it. 1324 1325 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1326 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1327 or the sequence like 1328 .vb 1329 `PetscViewer` v; 1330 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1331 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1332 `PetscViewerSetFromOptions`(v); 1333 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1334 `PetscViewerFileSetName`(v,"datafile"); 1335 .ve 1336 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1337 $ -viewer_type {binary, hdf5} 1338 1339 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1340 and src/mat/tutorials/ex10.c with the second approach. 1341 1342 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1343 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1344 Multiple objects, both matrices and vectors, can be stored within the same file. 1345 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1346 1347 Most users should not need to know the details of the binary storage 1348 format, since `MatLoad()` and `MatView()` completely hide these details. 1349 But for anyone who is interested, the standard binary matrix storage 1350 format is 1351 1352 .vb 1353 PetscInt MAT_FILE_CLASSID 1354 PetscInt number of rows 1355 PetscInt number of columns 1356 PetscInt total number of nonzeros 1357 PetscInt *number nonzeros in each row 1358 PetscInt *column indices of all nonzeros (starting index is zero) 1359 PetscScalar *values of all nonzeros 1360 .ve 1361 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1362 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 1363 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1364 1365 PETSc automatically does the byte swapping for 1366 machines that store the bytes reversed. Thus if you write your own binary 1367 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1368 and `PetscBinaryWrite()` to see how this may be done. 1369 1370 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1371 Each processor's chunk is loaded independently by its owning MPI process. 1372 Multiple objects, both matrices and vectors, can be stored within the same file. 1373 They are looked up by their PetscObject name. 1374 1375 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1376 by default the same structure and naming of the AIJ arrays and column count 1377 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1378 $ save example.mat A b -v7.3 1379 can be directly read by this routine (see Reference 1 for details). 1380 1381 Depending on your MATLAB version, this format might be a default, 1382 otherwise you can set it as default in Preferences. 1383 1384 Unless -nocompression flag is used to save the file in MATLAB, 1385 PETSc must be configured with ZLIB package. 1386 1387 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1388 1389 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1390 1391 Corresponding `MatView()` is not yet implemented. 1392 1393 The loaded matrix is actually a transpose of the original one in MATLAB, 1394 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1395 With this format, matrix is automatically transposed by PETSc, 1396 unless the matrix is marked as SPD or symmetric 1397 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1398 1399 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1400 1401 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1402 @*/ 1403 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1404 { 1405 PetscBool flg; 1406 1407 PetscFunctionBegin; 1408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1409 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1410 1411 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1412 1413 flg = PETSC_FALSE; 1414 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1415 if (flg) { 1416 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1417 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1418 } 1419 flg = PETSC_FALSE; 1420 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1421 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1422 1423 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1424 PetscUseTypeMethod(mat, load, viewer); 1425 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1426 PetscFunctionReturn(PETSC_SUCCESS); 1427 } 1428 1429 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1430 { 1431 Mat_Redundant *redund = *redundant; 1432 1433 PetscFunctionBegin; 1434 if (redund) { 1435 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1436 PetscCall(ISDestroy(&redund->isrow)); 1437 PetscCall(ISDestroy(&redund->iscol)); 1438 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1439 } else { 1440 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1441 PetscCall(PetscFree(redund->sbuf_j)); 1442 PetscCall(PetscFree(redund->sbuf_a)); 1443 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1444 PetscCall(PetscFree(redund->rbuf_j[i])); 1445 PetscCall(PetscFree(redund->rbuf_a[i])); 1446 } 1447 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1448 } 1449 1450 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1451 PetscCall(PetscFree(redund)); 1452 } 1453 PetscFunctionReturn(PETSC_SUCCESS); 1454 } 1455 1456 /*@ 1457 MatDestroy - Frees space taken by a matrix. 1458 1459 Collective 1460 1461 Input Parameter: 1462 . A - the matrix 1463 1464 Level: beginner 1465 1466 Developer Note: 1467 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1468 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1469 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1470 if changes are needed here. 1471 1472 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1473 @*/ 1474 PetscErrorCode MatDestroy(Mat *A) 1475 { 1476 PetscFunctionBegin; 1477 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1478 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1479 if (--((PetscObject)*A)->refct > 0) { 1480 *A = NULL; 1481 PetscFunctionReturn(PETSC_SUCCESS); 1482 } 1483 1484 /* if memory was published with SAWs then destroy it */ 1485 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1486 PetscTryTypeMethod(*A, destroy); 1487 1488 PetscCall(PetscFree((*A)->factorprefix)); 1489 PetscCall(PetscFree((*A)->defaultvectype)); 1490 PetscCall(PetscFree((*A)->defaultrandtype)); 1491 PetscCall(PetscFree((*A)->bsizes)); 1492 PetscCall(PetscFree((*A)->solvertype)); 1493 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1494 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1495 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1496 PetscCall(MatProductClear(*A)); 1497 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1498 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1499 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1500 PetscCall(MatDestroy(&(*A)->schur)); 1501 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1502 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1503 PetscCall(PetscHeaderDestroy(A)); 1504 PetscFunctionReturn(PETSC_SUCCESS); 1505 } 1506 1507 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1508 /*@ 1509 MatSetValues - Inserts or adds a block of values into a matrix. 1510 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1511 MUST be called after all calls to `MatSetValues()` have been completed. 1512 1513 Not Collective 1514 1515 Input Parameters: 1516 + mat - the matrix 1517 . v - a logically two-dimensional array of values 1518 . m - the number of rows 1519 . idxm - the global indices of the rows 1520 . n - the number of columns 1521 . idxn - the global indices of the columns 1522 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1523 1524 Level: beginner 1525 1526 Notes: 1527 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1528 1529 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1530 options cannot be mixed without intervening calls to the assembly 1531 routines. 1532 1533 `MatSetValues()` uses 0-based row and column numbers in Fortran 1534 as well as in C. 1535 1536 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1537 simply ignored. This allows easily inserting element stiffness matrices 1538 with homogeneous Dirichlet boundary conditions that you don't want represented 1539 in the matrix. 1540 1541 Efficiency Alert: 1542 The routine `MatSetValuesBlocked()` may offer much better efficiency 1543 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1544 1545 Fortran Notes: 1546 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1547 .vb 1548 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1549 .ve 1550 1551 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1552 1553 Developer Note: 1554 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1555 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1556 1557 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1559 @*/ 1560 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1561 { 1562 PetscFunctionBeginHot; 1563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1564 PetscValidType(mat, 1); 1565 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1566 PetscAssertPointer(idxm, 3); 1567 PetscAssertPointer(idxn, 5); 1568 MatCheckPreallocated(mat, 1); 1569 1570 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1571 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1572 1573 if (PetscDefined(USE_DEBUG)) { 1574 PetscInt i, j; 1575 1576 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1577 if (v) { 1578 for (i = 0; i < m; i++) { 1579 for (j = 0; j < n; j++) { 1580 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1581 #if defined(PETSC_USE_COMPLEX) 1582 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]); 1583 #else 1584 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]); 1585 #endif 1586 } 1587 } 1588 } 1589 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); 1590 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); 1591 } 1592 1593 if (mat->assembled) { 1594 mat->was_assembled = PETSC_TRUE; 1595 mat->assembled = PETSC_FALSE; 1596 } 1597 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1598 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1599 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1600 PetscFunctionReturn(PETSC_SUCCESS); 1601 } 1602 1603 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1604 /*@ 1605 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1606 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1607 MUST be called after all calls to `MatSetValues()` have been completed. 1608 1609 Not Collective 1610 1611 Input Parameters: 1612 + mat - the matrix 1613 . v - a logically two-dimensional array of values 1614 . ism - the rows to provide 1615 . isn - the columns to provide 1616 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1617 1618 Level: beginner 1619 1620 Notes: 1621 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1622 1623 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1624 options cannot be mixed without intervening calls to the assembly 1625 routines. 1626 1627 `MatSetValues()` uses 0-based row and column numbers in Fortran 1628 as well as in C. 1629 1630 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1631 simply ignored. This allows easily inserting element stiffness matrices 1632 with homogeneous Dirichlet boundary conditions that you don't want represented 1633 in the matrix. 1634 1635 Efficiency Alert: 1636 The routine `MatSetValuesBlocked()` may offer much better efficiency 1637 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1638 1639 This is currently not optimized for any particular `ISType` 1640 1641 Developer Note: 1642 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1643 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1644 1645 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1646 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1647 @*/ 1648 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1649 { 1650 PetscInt m, n; 1651 const PetscInt *rows, *cols; 1652 1653 PetscFunctionBeginHot; 1654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1655 PetscCall(ISGetIndices(ism, &rows)); 1656 PetscCall(ISGetIndices(isn, &cols)); 1657 PetscCall(ISGetLocalSize(ism, &m)); 1658 PetscCall(ISGetLocalSize(isn, &n)); 1659 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1660 PetscCall(ISRestoreIndices(ism, &rows)); 1661 PetscCall(ISRestoreIndices(isn, &cols)); 1662 PetscFunctionReturn(PETSC_SUCCESS); 1663 } 1664 1665 /*@ 1666 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1667 values into a matrix 1668 1669 Not Collective 1670 1671 Input Parameters: 1672 + mat - the matrix 1673 . row - the (block) row to set 1674 - v - a logically two-dimensional array of values 1675 1676 Level: intermediate 1677 1678 Notes: 1679 The values, `v`, are column-oriented (for the block version) and sorted 1680 1681 All the nonzero values in `row` must be provided 1682 1683 The matrix must have previously had its column indices set, likely by having been assembled. 1684 1685 `row` must belong to this MPI process 1686 1687 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1688 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1689 @*/ 1690 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1691 { 1692 PetscInt globalrow; 1693 1694 PetscFunctionBegin; 1695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1696 PetscValidType(mat, 1); 1697 PetscAssertPointer(v, 3); 1698 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1699 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1700 PetscFunctionReturn(PETSC_SUCCESS); 1701 } 1702 1703 /*@ 1704 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1705 values into a matrix 1706 1707 Not Collective 1708 1709 Input Parameters: 1710 + mat - the matrix 1711 . row - the (block) row to set 1712 - 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 1713 1714 Level: advanced 1715 1716 Notes: 1717 The values, `v`, are column-oriented for the block version. 1718 1719 All the nonzeros in `row` must be provided 1720 1721 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1722 1723 `row` must belong to this process 1724 1725 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1726 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1727 @*/ 1728 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1729 { 1730 PetscFunctionBeginHot; 1731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1732 PetscValidType(mat, 1); 1733 MatCheckPreallocated(mat, 1); 1734 PetscAssertPointer(v, 3); 1735 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1736 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1737 mat->insertmode = INSERT_VALUES; 1738 1739 if (mat->assembled) { 1740 mat->was_assembled = PETSC_TRUE; 1741 mat->assembled = PETSC_FALSE; 1742 } 1743 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1744 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1745 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1746 PetscFunctionReturn(PETSC_SUCCESS); 1747 } 1748 1749 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1750 /*@ 1751 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1752 Using structured grid indexing 1753 1754 Not Collective 1755 1756 Input Parameters: 1757 + mat - the matrix 1758 . m - number of rows being entered 1759 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1760 . n - number of columns being entered 1761 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1762 . v - a logically two-dimensional array of values 1763 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1764 1765 Level: beginner 1766 1767 Notes: 1768 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1769 1770 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1771 options cannot be mixed without intervening calls to the assembly 1772 routines. 1773 1774 The grid coordinates are across the entire grid, not just the local portion 1775 1776 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1777 as well as in C. 1778 1779 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1780 1781 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1782 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1783 1784 The columns and rows in the stencil passed in MUST be contained within the 1785 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1786 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1787 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1788 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1789 1790 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1791 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1792 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1793 `DM_BOUNDARY_PERIODIC` boundary type. 1794 1795 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 1796 a single value per point) you can skip filling those indices. 1797 1798 Inspired by the structured grid interface to the HYPRE package 1799 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1800 1801 Efficiency Alert: 1802 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1803 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1804 1805 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1806 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1807 @*/ 1808 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1809 { 1810 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1811 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1812 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1813 1814 PetscFunctionBegin; 1815 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1816 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1817 PetscValidType(mat, 1); 1818 PetscAssertPointer(idxm, 3); 1819 PetscAssertPointer(idxn, 5); 1820 1821 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1822 jdxm = buf; 1823 jdxn = buf + m; 1824 } else { 1825 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1826 jdxm = bufm; 1827 jdxn = bufn; 1828 } 1829 for (i = 0; i < m; i++) { 1830 for (j = 0; j < 3 - sdim; j++) dxm++; 1831 tmp = *dxm++ - starts[0]; 1832 for (j = 0; j < dim - 1; j++) { 1833 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1834 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1835 } 1836 if (mat->stencil.noc) dxm++; 1837 jdxm[i] = tmp; 1838 } 1839 for (i = 0; i < n; i++) { 1840 for (j = 0; j < 3 - sdim; j++) dxn++; 1841 tmp = *dxn++ - starts[0]; 1842 for (j = 0; j < dim - 1; j++) { 1843 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1844 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1845 } 1846 if (mat->stencil.noc) dxn++; 1847 jdxn[i] = tmp; 1848 } 1849 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1850 PetscCall(PetscFree2(bufm, bufn)); 1851 PetscFunctionReturn(PETSC_SUCCESS); 1852 } 1853 1854 /*@ 1855 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1856 Using structured grid indexing 1857 1858 Not Collective 1859 1860 Input Parameters: 1861 + mat - the matrix 1862 . m - number of rows being entered 1863 . idxm - grid coordinates for matrix rows being entered 1864 . n - number of columns being entered 1865 . idxn - grid coordinates for matrix columns being entered 1866 . v - a logically two-dimensional array of values 1867 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1868 1869 Level: beginner 1870 1871 Notes: 1872 By default the values, `v`, are row-oriented and unsorted. 1873 See `MatSetOption()` for other options. 1874 1875 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1876 options cannot be mixed without intervening calls to the assembly 1877 routines. 1878 1879 The grid coordinates are across the entire grid, not just the local portion 1880 1881 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1882 as well as in C. 1883 1884 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1885 1886 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1887 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1888 1889 The columns and rows in the stencil passed in MUST be contained within the 1890 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1891 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1892 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1893 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1894 1895 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1896 simply ignored. This allows easily inserting element stiffness matrices 1897 with homogeneous Dirichlet boundary conditions that you don't want represented 1898 in the matrix. 1899 1900 Inspired by the structured grid interface to the HYPRE package 1901 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1902 1903 Fortran Note: 1904 `idxm` and `idxn` should be declared as 1905 .vb 1906 MatStencil idxm(4,m),idxn(4,n) 1907 .ve 1908 and the values inserted using 1909 .vb 1910 idxm(MatStencil_i,1) = i 1911 idxm(MatStencil_j,1) = j 1912 idxm(MatStencil_k,1) = k 1913 etc 1914 .ve 1915 1916 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1917 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1918 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1919 @*/ 1920 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1921 { 1922 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1923 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1924 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1925 1926 PetscFunctionBegin; 1927 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1929 PetscValidType(mat, 1); 1930 PetscAssertPointer(idxm, 3); 1931 PetscAssertPointer(idxn, 5); 1932 PetscAssertPointer(v, 6); 1933 1934 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1935 jdxm = buf; 1936 jdxn = buf + m; 1937 } else { 1938 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1939 jdxm = bufm; 1940 jdxn = bufn; 1941 } 1942 for (i = 0; i < m; i++) { 1943 for (j = 0; j < 3 - sdim; j++) dxm++; 1944 tmp = *dxm++ - starts[0]; 1945 for (j = 0; j < sdim - 1; j++) { 1946 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1947 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1948 } 1949 dxm++; 1950 jdxm[i] = tmp; 1951 } 1952 for (i = 0; i < n; i++) { 1953 for (j = 0; j < 3 - sdim; j++) dxn++; 1954 tmp = *dxn++ - starts[0]; 1955 for (j = 0; j < sdim - 1; j++) { 1956 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1957 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1958 } 1959 dxn++; 1960 jdxn[i] = tmp; 1961 } 1962 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1963 PetscCall(PetscFree2(bufm, bufn)); 1964 PetscFunctionReturn(PETSC_SUCCESS); 1965 } 1966 1967 /*@ 1968 MatSetStencil - Sets the grid information for setting values into a matrix via 1969 `MatSetValuesStencil()` 1970 1971 Not Collective 1972 1973 Input Parameters: 1974 + mat - the matrix 1975 . dim - dimension of the grid 1, 2, or 3 1976 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1977 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1978 - dof - number of degrees of freedom per node 1979 1980 Level: beginner 1981 1982 Notes: 1983 Inspired by the structured grid interface to the HYPRE package 1984 (www.llnl.gov/CASC/hyper) 1985 1986 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1987 user. 1988 1989 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1990 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1991 @*/ 1992 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1993 { 1994 PetscFunctionBegin; 1995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1996 PetscAssertPointer(dims, 3); 1997 PetscAssertPointer(starts, 4); 1998 1999 mat->stencil.dim = dim + (dof > 1); 2000 for (PetscInt i = 0; i < dim; i++) { 2001 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2002 mat->stencil.starts[i] = starts[dim - i - 1]; 2003 } 2004 mat->stencil.dims[dim] = dof; 2005 mat->stencil.starts[dim] = 0; 2006 mat->stencil.noc = (PetscBool)(dof == 1); 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 2010 /*@ 2011 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2012 2013 Not Collective 2014 2015 Input Parameters: 2016 + mat - the matrix 2017 . v - a logically two-dimensional array of values 2018 . m - the number of block rows 2019 . idxm - the global block indices 2020 . n - the number of block columns 2021 . idxn - the global block indices 2022 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2023 2024 Level: intermediate 2025 2026 Notes: 2027 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2028 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2029 2030 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2031 NOT the total number of rows/columns; for example, if the block size is 2 and 2032 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2033 The values in `idxm` would be 1 2; that is the first index for each block divided by 2034 the block size. 2035 2036 You must call `MatSetBlockSize()` when constructing this matrix (before 2037 preallocating it). 2038 2039 By default the values, `v`, are row-oriented, so the layout of 2040 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2041 2042 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2043 options cannot be mixed without intervening calls to the assembly 2044 routines. 2045 2046 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2047 as well as in C. 2048 2049 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2050 simply ignored. This allows easily inserting element stiffness matrices 2051 with homogeneous Dirichlet boundary conditions that you don't want represented 2052 in the matrix. 2053 2054 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2055 internal searching must be done to determine where to place the 2056 data in the matrix storage space. By instead inserting blocks of 2057 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2058 reduced. 2059 2060 Example: 2061 .vb 2062 Suppose m=n=2 and block size(bs) = 2 The array is 2063 2064 1 2 | 3 4 2065 5 6 | 7 8 2066 - - - | - - - 2067 9 10 | 11 12 2068 13 14 | 15 16 2069 2070 v[] should be passed in like 2071 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2072 2073 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2074 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2075 .ve 2076 2077 Fortran Notes: 2078 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2079 .vb 2080 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2081 .ve 2082 2083 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2084 2085 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2086 @*/ 2087 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2088 { 2089 PetscFunctionBeginHot; 2090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2091 PetscValidType(mat, 1); 2092 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2093 PetscAssertPointer(idxm, 3); 2094 PetscAssertPointer(idxn, 5); 2095 MatCheckPreallocated(mat, 1); 2096 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2097 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2098 if (PetscDefined(USE_DEBUG)) { 2099 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2100 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2101 } 2102 if (PetscDefined(USE_DEBUG)) { 2103 PetscInt rbs, cbs, M, N, i; 2104 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2105 PetscCall(MatGetSize(mat, &M, &N)); 2106 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); 2107 for (i = 0; i < n; i++) 2108 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); 2109 } 2110 if (mat->assembled) { 2111 mat->was_assembled = PETSC_TRUE; 2112 mat->assembled = PETSC_FALSE; 2113 } 2114 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2115 if (mat->ops->setvaluesblocked) { 2116 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2117 } else { 2118 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2119 PetscInt i, j, bs, cbs; 2120 2121 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2122 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2123 iidxm = buf; 2124 iidxn = buf + m * bs; 2125 } else { 2126 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2127 iidxm = bufr; 2128 iidxn = bufc; 2129 } 2130 for (i = 0; i < m; i++) { 2131 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2132 } 2133 if (m != n || bs != cbs || idxm != idxn) { 2134 for (i = 0; i < n; i++) { 2135 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2136 } 2137 } else iidxn = iidxm; 2138 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2139 PetscCall(PetscFree2(bufr, bufc)); 2140 } 2141 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2142 PetscFunctionReturn(PETSC_SUCCESS); 2143 } 2144 2145 /*@ 2146 MatGetValues - Gets a block of local values from a matrix. 2147 2148 Not Collective; can only return values that are owned by the give process 2149 2150 Input Parameters: 2151 + mat - the matrix 2152 . v - a logically two-dimensional array for storing the values 2153 . m - the number of rows 2154 . idxm - the global indices of the rows 2155 . n - the number of columns 2156 - idxn - the global indices of the columns 2157 2158 Level: advanced 2159 2160 Notes: 2161 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2162 The values, `v`, are then returned in a row-oriented format, 2163 analogous to that used by default in `MatSetValues()`. 2164 2165 `MatGetValues()` uses 0-based row and column numbers in 2166 Fortran as well as in C. 2167 2168 `MatGetValues()` requires that the matrix has been assembled 2169 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2170 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2171 without intermediate matrix assembly. 2172 2173 Negative row or column indices will be ignored and those locations in `v` will be 2174 left unchanged. 2175 2176 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2177 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2178 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2179 2180 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2181 @*/ 2182 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2183 { 2184 PetscFunctionBegin; 2185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2186 PetscValidType(mat, 1); 2187 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2188 PetscAssertPointer(idxm, 3); 2189 PetscAssertPointer(idxn, 5); 2190 PetscAssertPointer(v, 6); 2191 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2192 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2193 MatCheckPreallocated(mat, 1); 2194 2195 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2196 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2197 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2198 PetscFunctionReturn(PETSC_SUCCESS); 2199 } 2200 2201 /*@ 2202 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2203 defined previously by `MatSetLocalToGlobalMapping()` 2204 2205 Not Collective 2206 2207 Input Parameters: 2208 + mat - the matrix 2209 . nrow - number of rows 2210 . irow - the row local indices 2211 . ncol - number of columns 2212 - icol - the column local indices 2213 2214 Output Parameter: 2215 . y - a logically two-dimensional array of values 2216 2217 Level: advanced 2218 2219 Notes: 2220 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2221 2222 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, 2223 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2224 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2225 with `MatSetLocalToGlobalMapping()`. 2226 2227 Developer Note: 2228 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2229 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2230 2231 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2232 `MatSetValuesLocal()`, `MatGetValues()` 2233 @*/ 2234 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2235 { 2236 PetscFunctionBeginHot; 2237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2238 PetscValidType(mat, 1); 2239 MatCheckPreallocated(mat, 1); 2240 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2241 PetscAssertPointer(irow, 3); 2242 PetscAssertPointer(icol, 5); 2243 if (PetscDefined(USE_DEBUG)) { 2244 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2245 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2246 } 2247 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2248 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2249 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2250 else { 2251 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2252 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2253 irowm = buf; 2254 icolm = buf + nrow; 2255 } else { 2256 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2257 irowm = bufr; 2258 icolm = bufc; 2259 } 2260 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2261 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2262 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2263 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2264 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2265 PetscCall(PetscFree2(bufr, bufc)); 2266 } 2267 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2268 PetscFunctionReturn(PETSC_SUCCESS); 2269 } 2270 2271 /*@ 2272 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2273 the same size. Currently, this can only be called once and creates the given matrix. 2274 2275 Not Collective 2276 2277 Input Parameters: 2278 + mat - the matrix 2279 . nb - the number of blocks 2280 . bs - the number of rows (and columns) in each block 2281 . rows - a concatenation of the rows for each block 2282 - v - a concatenation of logically two-dimensional arrays of values 2283 2284 Level: advanced 2285 2286 Notes: 2287 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2288 2289 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2290 2291 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2292 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2293 @*/ 2294 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2295 { 2296 PetscFunctionBegin; 2297 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2298 PetscValidType(mat, 1); 2299 PetscAssertPointer(rows, 4); 2300 PetscAssertPointer(v, 5); 2301 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2302 2303 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2304 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2305 else { 2306 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2307 } 2308 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2309 PetscFunctionReturn(PETSC_SUCCESS); 2310 } 2311 2312 /*@ 2313 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2314 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2315 using a local (per-processor) numbering. 2316 2317 Not Collective 2318 2319 Input Parameters: 2320 + x - the matrix 2321 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2322 - cmapping - column mapping 2323 2324 Level: intermediate 2325 2326 Note: 2327 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2328 2329 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2330 @*/ 2331 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2332 { 2333 PetscFunctionBegin; 2334 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2335 PetscValidType(x, 1); 2336 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2337 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2338 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2339 else { 2340 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2341 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2342 } 2343 PetscFunctionReturn(PETSC_SUCCESS); 2344 } 2345 2346 /*@ 2347 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2348 2349 Not Collective 2350 2351 Input Parameter: 2352 . A - the matrix 2353 2354 Output Parameters: 2355 + rmapping - row mapping 2356 - cmapping - column mapping 2357 2358 Level: advanced 2359 2360 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2361 @*/ 2362 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2363 { 2364 PetscFunctionBegin; 2365 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2366 PetscValidType(A, 1); 2367 if (rmapping) { 2368 PetscAssertPointer(rmapping, 2); 2369 *rmapping = A->rmap->mapping; 2370 } 2371 if (cmapping) { 2372 PetscAssertPointer(cmapping, 3); 2373 *cmapping = A->cmap->mapping; 2374 } 2375 PetscFunctionReturn(PETSC_SUCCESS); 2376 } 2377 2378 /*@ 2379 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2380 2381 Logically Collective 2382 2383 Input Parameters: 2384 + A - the matrix 2385 . rmap - row layout 2386 - cmap - column layout 2387 2388 Level: advanced 2389 2390 Note: 2391 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2392 2393 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2394 @*/ 2395 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2396 { 2397 PetscFunctionBegin; 2398 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2399 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2400 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2401 PetscFunctionReturn(PETSC_SUCCESS); 2402 } 2403 2404 /*@ 2405 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2406 2407 Not Collective 2408 2409 Input Parameter: 2410 . A - the matrix 2411 2412 Output Parameters: 2413 + rmap - row layout 2414 - cmap - column layout 2415 2416 Level: advanced 2417 2418 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2419 @*/ 2420 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2421 { 2422 PetscFunctionBegin; 2423 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2424 PetscValidType(A, 1); 2425 if (rmap) { 2426 PetscAssertPointer(rmap, 2); 2427 *rmap = A->rmap; 2428 } 2429 if (cmap) { 2430 PetscAssertPointer(cmap, 3); 2431 *cmap = A->cmap; 2432 } 2433 PetscFunctionReturn(PETSC_SUCCESS); 2434 } 2435 2436 /*@ 2437 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2438 using a local numbering of the rows and columns. 2439 2440 Not Collective 2441 2442 Input Parameters: 2443 + mat - the matrix 2444 . nrow - number of rows 2445 . irow - the row local indices 2446 . ncol - number of columns 2447 . icol - the column local indices 2448 . y - a logically two-dimensional array of values 2449 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2450 2451 Level: intermediate 2452 2453 Notes: 2454 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2455 2456 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2457 options cannot be mixed without intervening calls to the assembly 2458 routines. 2459 2460 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2461 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2462 2463 Fortran Notes: 2464 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2465 .vb 2466 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2467 .ve 2468 2469 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2470 2471 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2472 `MatGetValuesLocal()` 2473 @*/ 2474 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2475 { 2476 PetscFunctionBeginHot; 2477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2478 PetscValidType(mat, 1); 2479 MatCheckPreallocated(mat, 1); 2480 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2481 PetscAssertPointer(irow, 3); 2482 PetscAssertPointer(icol, 5); 2483 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2484 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2485 if (PetscDefined(USE_DEBUG)) { 2486 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2487 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2488 } 2489 2490 if (mat->assembled) { 2491 mat->was_assembled = PETSC_TRUE; 2492 mat->assembled = PETSC_FALSE; 2493 } 2494 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2495 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2496 else { 2497 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2498 const PetscInt *irowm, *icolm; 2499 2500 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2501 bufr = buf; 2502 bufc = buf + nrow; 2503 irowm = bufr; 2504 icolm = bufc; 2505 } else { 2506 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2507 irowm = bufr; 2508 icolm = bufc; 2509 } 2510 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2511 else irowm = irow; 2512 if (mat->cmap->mapping) { 2513 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2514 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2515 } else icolm = irowm; 2516 } else icolm = icol; 2517 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2518 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2519 } 2520 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2521 PetscFunctionReturn(PETSC_SUCCESS); 2522 } 2523 2524 /*@ 2525 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2526 using a local ordering of the nodes a block at a time. 2527 2528 Not Collective 2529 2530 Input Parameters: 2531 + mat - the matrix 2532 . nrow - number of rows 2533 . irow - the row local indices 2534 . ncol - number of columns 2535 . icol - the column local indices 2536 . y - a logically two-dimensional array of values 2537 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2538 2539 Level: intermediate 2540 2541 Notes: 2542 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2543 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2544 2545 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2546 options cannot be mixed without intervening calls to the assembly 2547 routines. 2548 2549 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2550 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2551 2552 Fortran Notes: 2553 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2554 .vb 2555 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2556 .ve 2557 2558 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2559 2560 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2561 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2562 @*/ 2563 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2564 { 2565 PetscFunctionBeginHot; 2566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2567 PetscValidType(mat, 1); 2568 MatCheckPreallocated(mat, 1); 2569 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2570 PetscAssertPointer(irow, 3); 2571 PetscAssertPointer(icol, 5); 2572 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2573 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2574 if (PetscDefined(USE_DEBUG)) { 2575 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2576 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); 2577 } 2578 2579 if (mat->assembled) { 2580 mat->was_assembled = PETSC_TRUE; 2581 mat->assembled = PETSC_FALSE; 2582 } 2583 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2584 PetscInt irbs, rbs; 2585 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2586 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2587 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2588 } 2589 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2590 PetscInt icbs, cbs; 2591 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2592 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2593 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2594 } 2595 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2596 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2597 else { 2598 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2599 const PetscInt *irowm, *icolm; 2600 2601 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2602 bufr = buf; 2603 bufc = buf + nrow; 2604 irowm = bufr; 2605 icolm = bufc; 2606 } else { 2607 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2608 irowm = bufr; 2609 icolm = bufc; 2610 } 2611 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2612 else irowm = irow; 2613 if (mat->cmap->mapping) { 2614 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2615 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2616 } else icolm = irowm; 2617 } else icolm = icol; 2618 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2619 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2620 } 2621 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2622 PetscFunctionReturn(PETSC_SUCCESS); 2623 } 2624 2625 /*@ 2626 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2627 2628 Collective 2629 2630 Input Parameters: 2631 + mat - the matrix 2632 - x - the vector to be multiplied 2633 2634 Output Parameter: 2635 . y - the result 2636 2637 Level: developer 2638 2639 Note: 2640 The vectors `x` and `y` cannot be the same. I.e., one cannot 2641 call `MatMultDiagonalBlock`(A,y,y). 2642 2643 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2644 @*/ 2645 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2646 { 2647 PetscFunctionBegin; 2648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2649 PetscValidType(mat, 1); 2650 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2651 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2652 2653 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2654 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2655 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2656 MatCheckPreallocated(mat, 1); 2657 2658 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2659 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2660 PetscFunctionReturn(PETSC_SUCCESS); 2661 } 2662 2663 /*@ 2664 MatMult - Computes the matrix-vector product, $y = Ax$. 2665 2666 Neighbor-wise Collective 2667 2668 Input Parameters: 2669 + mat - the matrix 2670 - x - the vector to be multiplied 2671 2672 Output Parameter: 2673 . y - the result 2674 2675 Level: beginner 2676 2677 Note: 2678 The vectors `x` and `y` cannot be the same. I.e., one cannot 2679 call `MatMult`(A,y,y). 2680 2681 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2682 @*/ 2683 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2684 { 2685 PetscFunctionBegin; 2686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2687 PetscValidType(mat, 1); 2688 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2689 VecCheckAssembled(x); 2690 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2691 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2692 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2693 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2694 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); 2695 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); 2696 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); 2697 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); 2698 PetscCall(VecSetErrorIfLocked(y, 3)); 2699 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2700 MatCheckPreallocated(mat, 1); 2701 2702 PetscCall(VecLockReadPush(x)); 2703 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2704 PetscUseTypeMethod(mat, mult, x, y); 2705 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2706 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2707 PetscCall(VecLockReadPop(x)); 2708 PetscFunctionReturn(PETSC_SUCCESS); 2709 } 2710 2711 /*@ 2712 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2713 2714 Neighbor-wise Collective 2715 2716 Input Parameters: 2717 + mat - the matrix 2718 - x - the vector to be multiplied 2719 2720 Output Parameter: 2721 . y - the result 2722 2723 Level: beginner 2724 2725 Notes: 2726 The vectors `x` and `y` cannot be the same. I.e., one cannot 2727 call `MatMultTranspose`(A,y,y). 2728 2729 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2730 use `MatMultHermitianTranspose()` 2731 2732 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2733 @*/ 2734 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2735 { 2736 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2737 2738 PetscFunctionBegin; 2739 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2740 PetscValidType(mat, 1); 2741 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2742 VecCheckAssembled(x); 2743 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2744 2745 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2746 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2747 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2748 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); 2749 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); 2750 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); 2751 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); 2752 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2753 MatCheckPreallocated(mat, 1); 2754 2755 if (!mat->ops->multtranspose) { 2756 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2757 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); 2758 } else op = mat->ops->multtranspose; 2759 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2760 PetscCall(VecLockReadPush(x)); 2761 PetscCall((*op)(mat, x, y)); 2762 PetscCall(VecLockReadPop(x)); 2763 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2764 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2765 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2766 PetscFunctionReturn(PETSC_SUCCESS); 2767 } 2768 2769 /*@ 2770 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2771 2772 Neighbor-wise Collective 2773 2774 Input Parameters: 2775 + mat - the matrix 2776 - x - the vector to be multiplied 2777 2778 Output Parameter: 2779 . y - the result 2780 2781 Level: beginner 2782 2783 Notes: 2784 The vectors `x` and `y` cannot be the same. I.e., one cannot 2785 call `MatMultHermitianTranspose`(A,y,y). 2786 2787 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2788 2789 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2790 2791 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2792 @*/ 2793 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2794 { 2795 PetscFunctionBegin; 2796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2797 PetscValidType(mat, 1); 2798 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2799 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2800 2801 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2802 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2803 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2804 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); 2805 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); 2806 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); 2807 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); 2808 MatCheckPreallocated(mat, 1); 2809 2810 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2811 #if defined(PETSC_USE_COMPLEX) 2812 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2813 PetscCall(VecLockReadPush(x)); 2814 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2815 else PetscUseTypeMethod(mat, mult, x, y); 2816 PetscCall(VecLockReadPop(x)); 2817 } else { 2818 Vec w; 2819 PetscCall(VecDuplicate(x, &w)); 2820 PetscCall(VecCopy(x, w)); 2821 PetscCall(VecConjugate(w)); 2822 PetscCall(MatMultTranspose(mat, w, y)); 2823 PetscCall(VecDestroy(&w)); 2824 PetscCall(VecConjugate(y)); 2825 } 2826 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2827 #else 2828 PetscCall(MatMultTranspose(mat, x, y)); 2829 #endif 2830 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2831 PetscFunctionReturn(PETSC_SUCCESS); 2832 } 2833 2834 /*@ 2835 MatMultAdd - Computes $v3 = v2 + A * v1$. 2836 2837 Neighbor-wise Collective 2838 2839 Input Parameters: 2840 + mat - the matrix 2841 . v1 - the vector to be multiplied by `mat` 2842 - v2 - the vector to be added to the result 2843 2844 Output Parameter: 2845 . v3 - the result 2846 2847 Level: beginner 2848 2849 Note: 2850 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2851 call `MatMultAdd`(A,v1,v2,v1). 2852 2853 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2854 @*/ 2855 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2856 { 2857 PetscFunctionBegin; 2858 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2859 PetscValidType(mat, 1); 2860 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2861 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2862 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2863 2864 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2865 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2866 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); 2867 /* 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); 2868 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); */ 2869 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); 2870 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); 2871 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2872 MatCheckPreallocated(mat, 1); 2873 2874 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2875 PetscCall(VecLockReadPush(v1)); 2876 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2877 PetscCall(VecLockReadPop(v1)); 2878 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2879 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2880 PetscFunctionReturn(PETSC_SUCCESS); 2881 } 2882 2883 /*@ 2884 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2885 2886 Neighbor-wise Collective 2887 2888 Input Parameters: 2889 + mat - the matrix 2890 . v1 - the vector to be multiplied by the transpose of the matrix 2891 - v2 - the vector to be added to the result 2892 2893 Output Parameter: 2894 . v3 - the result 2895 2896 Level: beginner 2897 2898 Note: 2899 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2900 call `MatMultTransposeAdd`(A,v1,v2,v1). 2901 2902 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2903 @*/ 2904 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2905 { 2906 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2907 2908 PetscFunctionBegin; 2909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2910 PetscValidType(mat, 1); 2911 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2912 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2913 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2914 2915 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2916 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2917 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); 2918 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); 2919 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); 2920 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2921 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2922 MatCheckPreallocated(mat, 1); 2923 2924 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2925 PetscCall(VecLockReadPush(v1)); 2926 PetscCall((*op)(mat, v1, v2, v3)); 2927 PetscCall(VecLockReadPop(v1)); 2928 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2929 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2930 PetscFunctionReturn(PETSC_SUCCESS); 2931 } 2932 2933 /*@ 2934 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2935 2936 Neighbor-wise Collective 2937 2938 Input Parameters: 2939 + mat - the matrix 2940 . v1 - the vector to be multiplied by the Hermitian transpose 2941 - v2 - the vector to be added to the result 2942 2943 Output Parameter: 2944 . v3 - the result 2945 2946 Level: beginner 2947 2948 Note: 2949 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2950 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2951 2952 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2953 @*/ 2954 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2955 { 2956 PetscFunctionBegin; 2957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2958 PetscValidType(mat, 1); 2959 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2960 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2961 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2962 2963 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2964 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2965 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2966 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); 2967 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); 2968 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); 2969 MatCheckPreallocated(mat, 1); 2970 2971 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2972 PetscCall(VecLockReadPush(v1)); 2973 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2974 else { 2975 Vec w, z; 2976 PetscCall(VecDuplicate(v1, &w)); 2977 PetscCall(VecCopy(v1, w)); 2978 PetscCall(VecConjugate(w)); 2979 PetscCall(VecDuplicate(v3, &z)); 2980 PetscCall(MatMultTranspose(mat, w, z)); 2981 PetscCall(VecDestroy(&w)); 2982 PetscCall(VecConjugate(z)); 2983 if (v2 != v3) { 2984 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2985 } else { 2986 PetscCall(VecAXPY(v3, 1.0, z)); 2987 } 2988 PetscCall(VecDestroy(&z)); 2989 } 2990 PetscCall(VecLockReadPop(v1)); 2991 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2992 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2993 PetscFunctionReturn(PETSC_SUCCESS); 2994 } 2995 2996 /*@ 2997 MatGetFactorType - gets the type of factorization a matrix is 2998 2999 Not Collective 3000 3001 Input Parameter: 3002 . mat - the matrix 3003 3004 Output Parameter: 3005 . 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` 3006 3007 Level: intermediate 3008 3009 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3010 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3011 @*/ 3012 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3013 { 3014 PetscFunctionBegin; 3015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3016 PetscValidType(mat, 1); 3017 PetscAssertPointer(t, 2); 3018 *t = mat->factortype; 3019 PetscFunctionReturn(PETSC_SUCCESS); 3020 } 3021 3022 /*@ 3023 MatSetFactorType - sets the type of factorization a matrix is 3024 3025 Logically Collective 3026 3027 Input Parameters: 3028 + mat - the matrix 3029 - 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` 3030 3031 Level: intermediate 3032 3033 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3034 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3035 @*/ 3036 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3037 { 3038 PetscFunctionBegin; 3039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3040 PetscValidType(mat, 1); 3041 mat->factortype = t; 3042 PetscFunctionReturn(PETSC_SUCCESS); 3043 } 3044 3045 /*@ 3046 MatGetInfo - Returns information about matrix storage (number of 3047 nonzeros, memory, etc.). 3048 3049 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3050 3051 Input Parameters: 3052 + mat - the matrix 3053 - 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) 3054 3055 Output Parameter: 3056 . info - matrix information context 3057 3058 Options Database Key: 3059 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3060 3061 Level: intermediate 3062 3063 Notes: 3064 The `MatInfo` context contains a variety of matrix data, including 3065 number of nonzeros allocated and used, number of mallocs during 3066 matrix assembly, etc. Additional information for factored matrices 3067 is provided (such as the fill ratio, number of mallocs during 3068 factorization, etc.). 3069 3070 Example: 3071 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3072 data within the `MatInfo` context. For example, 3073 .vb 3074 MatInfo info; 3075 Mat A; 3076 double mal, nz_a, nz_u; 3077 3078 MatGetInfo(A, MAT_LOCAL, &info); 3079 mal = info.mallocs; 3080 nz_a = info.nz_allocated; 3081 .ve 3082 3083 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3084 @*/ 3085 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3086 { 3087 PetscFunctionBegin; 3088 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3089 PetscValidType(mat, 1); 3090 PetscAssertPointer(info, 3); 3091 MatCheckPreallocated(mat, 1); 3092 PetscUseTypeMethod(mat, getinfo, flag, info); 3093 PetscFunctionReturn(PETSC_SUCCESS); 3094 } 3095 3096 /* 3097 This is used by external packages where it is not easy to get the info from the actual 3098 matrix factorization. 3099 */ 3100 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3101 { 3102 PetscFunctionBegin; 3103 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3104 PetscFunctionReturn(PETSC_SUCCESS); 3105 } 3106 3107 /*@ 3108 MatLUFactor - Performs in-place LU factorization of matrix. 3109 3110 Collective 3111 3112 Input Parameters: 3113 + mat - the matrix 3114 . row - row permutation 3115 . col - column permutation 3116 - info - options for factorization, includes 3117 .vb 3118 fill - expected fill as ratio of original fill. 3119 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3120 Run with the option -info to determine an optimal value to use 3121 .ve 3122 3123 Level: developer 3124 3125 Notes: 3126 Most users should employ the `KSP` interface for linear solvers 3127 instead of working directly with matrix algebra routines such as this. 3128 See, e.g., `KSPCreate()`. 3129 3130 This changes the state of the matrix to a factored matrix; it cannot be used 3131 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3132 3133 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3134 when not using `KSP`. 3135 3136 Developer Note: 3137 The Fortran interface is not autogenerated as the 3138 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3139 3140 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3141 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3142 @*/ 3143 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3144 { 3145 MatFactorInfo tinfo; 3146 3147 PetscFunctionBegin; 3148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3149 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3150 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3151 if (info) PetscAssertPointer(info, 4); 3152 PetscValidType(mat, 1); 3153 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3154 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3155 MatCheckPreallocated(mat, 1); 3156 if (!info) { 3157 PetscCall(MatFactorInfoInitialize(&tinfo)); 3158 info = &tinfo; 3159 } 3160 3161 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3162 PetscUseTypeMethod(mat, lufactor, row, col, info); 3163 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3164 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3165 PetscFunctionReturn(PETSC_SUCCESS); 3166 } 3167 3168 /*@ 3169 MatILUFactor - Performs in-place ILU factorization of matrix. 3170 3171 Collective 3172 3173 Input Parameters: 3174 + mat - the matrix 3175 . row - row permutation 3176 . col - column permutation 3177 - info - structure containing 3178 .vb 3179 levels - number of levels of fill. 3180 expected fill - as ratio of original fill. 3181 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3182 missing diagonal entries) 3183 .ve 3184 3185 Level: developer 3186 3187 Notes: 3188 Most users should employ the `KSP` interface for linear solvers 3189 instead of working directly with matrix algebra routines such as this. 3190 See, e.g., `KSPCreate()`. 3191 3192 Probably really in-place only when level of fill is zero, otherwise allocates 3193 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3194 when not using `KSP`. 3195 3196 Developer Note: 3197 The Fortran interface is not autogenerated as the 3198 interface definition cannot be generated correctly [due to MatFactorInfo] 3199 3200 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3201 @*/ 3202 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3203 { 3204 PetscFunctionBegin; 3205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3206 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3207 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3208 PetscAssertPointer(info, 4); 3209 PetscValidType(mat, 1); 3210 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3211 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3212 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3213 MatCheckPreallocated(mat, 1); 3214 3215 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3216 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3217 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3218 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3219 PetscFunctionReturn(PETSC_SUCCESS); 3220 } 3221 3222 /*@ 3223 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3224 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3225 3226 Collective 3227 3228 Input Parameters: 3229 + fact - the factor matrix obtained with `MatGetFactor()` 3230 . mat - the matrix 3231 . row - the row permutation 3232 . col - the column permutation 3233 - info - options for factorization, includes 3234 .vb 3235 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3236 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3237 .ve 3238 3239 Level: developer 3240 3241 Notes: 3242 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3243 3244 Most users should employ the simplified `KSP` interface for linear solvers 3245 instead of working directly with matrix algebra routines such as this. 3246 See, e.g., `KSPCreate()`. 3247 3248 Developer Note: 3249 The Fortran interface is not autogenerated as the 3250 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3251 3252 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3253 @*/ 3254 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3255 { 3256 MatFactorInfo tinfo; 3257 3258 PetscFunctionBegin; 3259 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3261 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3262 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3263 if (info) PetscAssertPointer(info, 5); 3264 PetscValidType(fact, 1); 3265 PetscValidType(mat, 2); 3266 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3267 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3268 MatCheckPreallocated(mat, 2); 3269 if (!info) { 3270 PetscCall(MatFactorInfoInitialize(&tinfo)); 3271 info = &tinfo; 3272 } 3273 3274 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3275 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3276 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3277 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3278 PetscFunctionReturn(PETSC_SUCCESS); 3279 } 3280 3281 /*@ 3282 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3283 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3284 3285 Collective 3286 3287 Input Parameters: 3288 + fact - the factor matrix obtained with `MatGetFactor()` 3289 . mat - the matrix 3290 - info - options for factorization 3291 3292 Level: developer 3293 3294 Notes: 3295 See `MatLUFactor()` for in-place factorization. See 3296 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3297 3298 Most users should employ the `KSP` interface for linear solvers 3299 instead of working directly with matrix algebra routines such as this. 3300 See, e.g., `KSPCreate()`. 3301 3302 Developer Note: 3303 The Fortran interface is not autogenerated as the 3304 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3305 3306 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3307 @*/ 3308 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3309 { 3310 MatFactorInfo tinfo; 3311 3312 PetscFunctionBegin; 3313 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3314 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3315 PetscValidType(fact, 1); 3316 PetscValidType(mat, 2); 3317 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3318 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, 3319 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3320 3321 MatCheckPreallocated(mat, 2); 3322 if (!info) { 3323 PetscCall(MatFactorInfoInitialize(&tinfo)); 3324 info = &tinfo; 3325 } 3326 3327 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3328 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3329 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3330 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3331 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3332 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3333 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3334 PetscFunctionReturn(PETSC_SUCCESS); 3335 } 3336 3337 /*@ 3338 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3339 symmetric matrix. 3340 3341 Collective 3342 3343 Input Parameters: 3344 + mat - the matrix 3345 . perm - row and column permutations 3346 - info - expected fill as ratio of original fill 3347 3348 Level: developer 3349 3350 Notes: 3351 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3352 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3353 3354 Most users should employ the `KSP` interface for linear solvers 3355 instead of working directly with matrix algebra routines such as this. 3356 See, e.g., `KSPCreate()`. 3357 3358 Developer Note: 3359 The Fortran interface is not autogenerated as the 3360 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3361 3362 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3363 `MatGetOrdering()` 3364 @*/ 3365 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3366 { 3367 MatFactorInfo tinfo; 3368 3369 PetscFunctionBegin; 3370 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3371 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3372 if (info) PetscAssertPointer(info, 3); 3373 PetscValidType(mat, 1); 3374 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3375 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3376 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3377 MatCheckPreallocated(mat, 1); 3378 if (!info) { 3379 PetscCall(MatFactorInfoInitialize(&tinfo)); 3380 info = &tinfo; 3381 } 3382 3383 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3384 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3385 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3386 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3387 PetscFunctionReturn(PETSC_SUCCESS); 3388 } 3389 3390 /*@ 3391 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3392 of a symmetric matrix. 3393 3394 Collective 3395 3396 Input Parameters: 3397 + fact - the factor matrix obtained with `MatGetFactor()` 3398 . mat - the matrix 3399 . perm - row and column permutations 3400 - info - options for factorization, includes 3401 .vb 3402 fill - expected fill as ratio of original fill. 3403 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3404 Run with the option -info to determine an optimal value to use 3405 .ve 3406 3407 Level: developer 3408 3409 Notes: 3410 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3411 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3412 3413 Most users should employ the `KSP` interface for linear solvers 3414 instead of working directly with matrix algebra routines such as this. 3415 See, e.g., `KSPCreate()`. 3416 3417 Developer Note: 3418 The Fortran interface is not autogenerated as the 3419 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3420 3421 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3422 `MatGetOrdering()` 3423 @*/ 3424 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3425 { 3426 MatFactorInfo tinfo; 3427 3428 PetscFunctionBegin; 3429 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3431 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3432 if (info) PetscAssertPointer(info, 4); 3433 PetscValidType(fact, 1); 3434 PetscValidType(mat, 2); 3435 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3436 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3437 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3438 MatCheckPreallocated(mat, 2); 3439 if (!info) { 3440 PetscCall(MatFactorInfoInitialize(&tinfo)); 3441 info = &tinfo; 3442 } 3443 3444 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3445 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3446 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3447 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3448 PetscFunctionReturn(PETSC_SUCCESS); 3449 } 3450 3451 /*@ 3452 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3453 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3454 `MatCholeskyFactorSymbolic()`. 3455 3456 Collective 3457 3458 Input Parameters: 3459 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3460 . mat - the initial matrix that is to be factored 3461 - info - options for factorization 3462 3463 Level: developer 3464 3465 Note: 3466 Most users should employ the `KSP` interface for linear solvers 3467 instead of working directly with matrix algebra routines such as this. 3468 See, e.g., `KSPCreate()`. 3469 3470 Developer Note: 3471 The Fortran interface is not autogenerated as the 3472 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3473 3474 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3475 @*/ 3476 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3477 { 3478 MatFactorInfo tinfo; 3479 3480 PetscFunctionBegin; 3481 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3482 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3483 PetscValidType(fact, 1); 3484 PetscValidType(mat, 2); 3485 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3486 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, 3487 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3488 MatCheckPreallocated(mat, 2); 3489 if (!info) { 3490 PetscCall(MatFactorInfoInitialize(&tinfo)); 3491 info = &tinfo; 3492 } 3493 3494 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3495 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3496 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3497 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3498 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3499 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3500 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3501 PetscFunctionReturn(PETSC_SUCCESS); 3502 } 3503 3504 /*@ 3505 MatQRFactor - Performs in-place QR factorization of matrix. 3506 3507 Collective 3508 3509 Input Parameters: 3510 + mat - the matrix 3511 . col - column permutation 3512 - info - options for factorization, includes 3513 .vb 3514 fill - expected fill as ratio of original fill. 3515 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3516 Run with the option -info to determine an optimal value to use 3517 .ve 3518 3519 Level: developer 3520 3521 Notes: 3522 Most users should employ the `KSP` interface for linear solvers 3523 instead of working directly with matrix algebra routines such as this. 3524 See, e.g., `KSPCreate()`. 3525 3526 This changes the state of the matrix to a factored matrix; it cannot be used 3527 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3528 3529 Developer Note: 3530 The Fortran interface is not autogenerated as the 3531 interface definition cannot be generated correctly [due to MatFactorInfo] 3532 3533 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3534 `MatSetUnfactored()` 3535 @*/ 3536 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3537 { 3538 PetscFunctionBegin; 3539 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3540 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3541 if (info) PetscAssertPointer(info, 3); 3542 PetscValidType(mat, 1); 3543 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3544 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3545 MatCheckPreallocated(mat, 1); 3546 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3547 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3548 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3549 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3550 PetscFunctionReturn(PETSC_SUCCESS); 3551 } 3552 3553 /*@ 3554 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3555 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3556 3557 Collective 3558 3559 Input Parameters: 3560 + fact - the factor matrix obtained with `MatGetFactor()` 3561 . mat - the matrix 3562 . col - column permutation 3563 - info - options for factorization, includes 3564 .vb 3565 fill - expected fill as ratio of original fill. 3566 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3567 Run with the option -info to determine an optimal value to use 3568 .ve 3569 3570 Level: developer 3571 3572 Note: 3573 Most users should employ the `KSP` interface for linear solvers 3574 instead of working directly with matrix algebra routines such as this. 3575 See, e.g., `KSPCreate()`. 3576 3577 Developer Note: 3578 The Fortran interface is not autogenerated as the 3579 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3580 3581 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3582 @*/ 3583 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3584 { 3585 MatFactorInfo tinfo; 3586 3587 PetscFunctionBegin; 3588 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3590 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3591 if (info) PetscAssertPointer(info, 4); 3592 PetscValidType(fact, 1); 3593 PetscValidType(mat, 2); 3594 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3595 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3596 MatCheckPreallocated(mat, 2); 3597 if (!info) { 3598 PetscCall(MatFactorInfoInitialize(&tinfo)); 3599 info = &tinfo; 3600 } 3601 3602 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3603 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3604 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3605 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3606 PetscFunctionReturn(PETSC_SUCCESS); 3607 } 3608 3609 /*@ 3610 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3611 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3612 3613 Collective 3614 3615 Input Parameters: 3616 + fact - the factor matrix obtained with `MatGetFactor()` 3617 . mat - the matrix 3618 - info - options for factorization 3619 3620 Level: developer 3621 3622 Notes: 3623 See `MatQRFactor()` for in-place factorization. 3624 3625 Most users should employ the `KSP` interface for linear solvers 3626 instead of working directly with matrix algebra routines such as this. 3627 See, e.g., `KSPCreate()`. 3628 3629 Developer Note: 3630 The Fortran interface is not autogenerated as the 3631 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3632 3633 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3634 @*/ 3635 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3636 { 3637 MatFactorInfo tinfo; 3638 3639 PetscFunctionBegin; 3640 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3642 PetscValidType(fact, 1); 3643 PetscValidType(mat, 2); 3644 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3645 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, 3646 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3647 3648 MatCheckPreallocated(mat, 2); 3649 if (!info) { 3650 PetscCall(MatFactorInfoInitialize(&tinfo)); 3651 info = &tinfo; 3652 } 3653 3654 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3655 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3656 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3657 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3658 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3659 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3660 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3661 PetscFunctionReturn(PETSC_SUCCESS); 3662 } 3663 3664 /*@ 3665 MatSolve - Solves $A x = b$, given a factored matrix. 3666 3667 Neighbor-wise Collective 3668 3669 Input Parameters: 3670 + mat - the factored matrix 3671 - b - the right-hand-side vector 3672 3673 Output Parameter: 3674 . x - the result vector 3675 3676 Level: developer 3677 3678 Notes: 3679 The vectors `b` and `x` cannot be the same. I.e., one cannot 3680 call `MatSolve`(A,x,x). 3681 3682 Most users should employ the `KSP` interface for linear solvers 3683 instead of working directly with matrix algebra routines such as this. 3684 See, e.g., `KSPCreate()`. 3685 3686 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3687 @*/ 3688 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3689 { 3690 PetscFunctionBegin; 3691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3692 PetscValidType(mat, 1); 3693 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3694 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3695 PetscCheckSameComm(mat, 1, b, 2); 3696 PetscCheckSameComm(mat, 1, x, 3); 3697 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3698 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); 3699 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); 3700 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); 3701 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3702 MatCheckPreallocated(mat, 1); 3703 3704 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3705 PetscCall(VecFlag(x, mat->factorerrortype)); 3706 if (mat->factorerrortype) { 3707 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3708 } else PetscUseTypeMethod(mat, solve, b, x); 3709 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3710 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3711 PetscFunctionReturn(PETSC_SUCCESS); 3712 } 3713 3714 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3715 { 3716 Vec b, x; 3717 PetscInt N, i; 3718 PetscErrorCode (*f)(Mat, Vec, Vec); 3719 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3720 3721 PetscFunctionBegin; 3722 if (A->factorerrortype) { 3723 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3724 PetscCall(MatSetInf(X)); 3725 PetscFunctionReturn(PETSC_SUCCESS); 3726 } 3727 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3728 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3729 PetscCall(MatBoundToCPU(A, &Abound)); 3730 if (!Abound) { 3731 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3732 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3733 } 3734 #if PetscDefined(HAVE_CUDA) 3735 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3736 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3737 #elif PetscDefined(HAVE_HIP) 3738 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3739 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3740 #endif 3741 PetscCall(MatGetSize(B, NULL, &N)); 3742 for (i = 0; i < N; i++) { 3743 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3744 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3745 PetscCall((*f)(A, b, x)); 3746 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3747 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3748 } 3749 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3750 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3751 PetscFunctionReturn(PETSC_SUCCESS); 3752 } 3753 3754 /*@ 3755 MatMatSolve - Solves $A X = B$, given a factored matrix. 3756 3757 Neighbor-wise Collective 3758 3759 Input Parameters: 3760 + A - the factored matrix 3761 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3762 3763 Output Parameter: 3764 . X - the result matrix (dense matrix) 3765 3766 Level: developer 3767 3768 Note: 3769 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3770 otherwise, `B` and `X` cannot be the same. 3771 3772 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3773 @*/ 3774 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3775 { 3776 PetscFunctionBegin; 3777 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3778 PetscValidType(A, 1); 3779 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3780 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3781 PetscCheckSameComm(A, 1, B, 2); 3782 PetscCheckSameComm(A, 1, X, 3); 3783 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3784 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3785 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3786 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3787 MatCheckPreallocated(A, 1); 3788 3789 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3790 if (!A->ops->matsolve) { 3791 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3792 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3793 } else PetscUseTypeMethod(A, matsolve, B, X); 3794 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3795 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3796 PetscFunctionReturn(PETSC_SUCCESS); 3797 } 3798 3799 /*@ 3800 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3801 3802 Neighbor-wise Collective 3803 3804 Input Parameters: 3805 + A - the factored matrix 3806 - B - the right-hand-side matrix (`MATDENSE` matrix) 3807 3808 Output Parameter: 3809 . X - the result matrix (dense matrix) 3810 3811 Level: developer 3812 3813 Note: 3814 The matrices `B` and `X` cannot be the same. I.e., one cannot 3815 call `MatMatSolveTranspose`(A,X,X). 3816 3817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3818 @*/ 3819 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3820 { 3821 PetscFunctionBegin; 3822 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3823 PetscValidType(A, 1); 3824 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3825 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3826 PetscCheckSameComm(A, 1, B, 2); 3827 PetscCheckSameComm(A, 1, X, 3); 3828 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3829 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); 3830 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); 3831 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); 3832 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"); 3833 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3834 MatCheckPreallocated(A, 1); 3835 3836 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3837 if (!A->ops->matsolvetranspose) { 3838 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3839 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3840 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3841 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3842 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3843 PetscFunctionReturn(PETSC_SUCCESS); 3844 } 3845 3846 /*@ 3847 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3848 3849 Neighbor-wise Collective 3850 3851 Input Parameters: 3852 + A - the factored matrix 3853 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3854 3855 Output Parameter: 3856 . X - the result matrix (dense matrix) 3857 3858 Level: developer 3859 3860 Note: 3861 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 3862 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3863 3864 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3865 @*/ 3866 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3867 { 3868 PetscFunctionBegin; 3869 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3870 PetscValidType(A, 1); 3871 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3872 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3873 PetscCheckSameComm(A, 1, Bt, 2); 3874 PetscCheckSameComm(A, 1, X, 3); 3875 3876 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3877 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); 3878 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); 3879 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"); 3880 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3881 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3882 MatCheckPreallocated(A, 1); 3883 3884 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3885 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3886 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3887 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3888 PetscFunctionReturn(PETSC_SUCCESS); 3889 } 3890 3891 /*@ 3892 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3893 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3894 3895 Neighbor-wise Collective 3896 3897 Input Parameters: 3898 + mat - the factored matrix 3899 - b - the right-hand-side vector 3900 3901 Output Parameter: 3902 . x - the result vector 3903 3904 Level: developer 3905 3906 Notes: 3907 `MatSolve()` should be used for most applications, as it performs 3908 a forward solve followed by a backward solve. 3909 3910 The vectors `b` and `x` cannot be the same, i.e., one cannot 3911 call `MatForwardSolve`(A,x,x). 3912 3913 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3914 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3915 `MatForwardSolve()` solves $U^T*D y = b$, and 3916 `MatBackwardSolve()` solves $U x = y$. 3917 Thus they do not provide a symmetric preconditioner. 3918 3919 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3920 @*/ 3921 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3922 { 3923 PetscFunctionBegin; 3924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3925 PetscValidType(mat, 1); 3926 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3927 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3928 PetscCheckSameComm(mat, 1, b, 2); 3929 PetscCheckSameComm(mat, 1, x, 3); 3930 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3931 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); 3932 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); 3933 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); 3934 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3935 MatCheckPreallocated(mat, 1); 3936 3937 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3938 PetscUseTypeMethod(mat, forwardsolve, b, x); 3939 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3940 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3941 PetscFunctionReturn(PETSC_SUCCESS); 3942 } 3943 3944 /*@ 3945 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3946 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3947 3948 Neighbor-wise Collective 3949 3950 Input Parameters: 3951 + mat - the factored matrix 3952 - b - the right-hand-side vector 3953 3954 Output Parameter: 3955 . x - the result vector 3956 3957 Level: developer 3958 3959 Notes: 3960 `MatSolve()` should be used for most applications, as it performs 3961 a forward solve followed by a backward solve. 3962 3963 The vectors `b` and `x` cannot be the same. I.e., one cannot 3964 call `MatBackwardSolve`(A,x,x). 3965 3966 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3967 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3968 `MatForwardSolve()` solves $U^T*D y = b$, and 3969 `MatBackwardSolve()` solves $U x = y$. 3970 Thus they do not provide a symmetric preconditioner. 3971 3972 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3973 @*/ 3974 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3975 { 3976 PetscFunctionBegin; 3977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3978 PetscValidType(mat, 1); 3979 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3980 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3981 PetscCheckSameComm(mat, 1, b, 2); 3982 PetscCheckSameComm(mat, 1, x, 3); 3983 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3984 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); 3985 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); 3986 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); 3987 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3988 MatCheckPreallocated(mat, 1); 3989 3990 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3991 PetscUseTypeMethod(mat, backwardsolve, b, x); 3992 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3993 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3994 PetscFunctionReturn(PETSC_SUCCESS); 3995 } 3996 3997 /*@ 3998 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3999 4000 Neighbor-wise Collective 4001 4002 Input Parameters: 4003 + mat - the factored matrix 4004 . b - the right-hand-side vector 4005 - y - the vector to be added to 4006 4007 Output Parameter: 4008 . x - the result vector 4009 4010 Level: developer 4011 4012 Note: 4013 The vectors `b` and `x` cannot be the same. I.e., one cannot 4014 call `MatSolveAdd`(A,x,y,x). 4015 4016 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4017 @*/ 4018 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4019 { 4020 PetscScalar one = 1.0; 4021 Vec tmp; 4022 4023 PetscFunctionBegin; 4024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4025 PetscValidType(mat, 1); 4026 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4027 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4028 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4029 PetscCheckSameComm(mat, 1, b, 2); 4030 PetscCheckSameComm(mat, 1, y, 3); 4031 PetscCheckSameComm(mat, 1, x, 4); 4032 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4033 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); 4034 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); 4035 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); 4036 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); 4037 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); 4038 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4039 MatCheckPreallocated(mat, 1); 4040 4041 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4042 PetscCall(VecFlag(x, mat->factorerrortype)); 4043 if (mat->factorerrortype) { 4044 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4045 } else if (mat->ops->solveadd) { 4046 PetscUseTypeMethod(mat, solveadd, b, y, x); 4047 } else { 4048 /* do the solve then the add manually */ 4049 if (x != y) { 4050 PetscCall(MatSolve(mat, b, x)); 4051 PetscCall(VecAXPY(x, one, y)); 4052 } else { 4053 PetscCall(VecDuplicate(x, &tmp)); 4054 PetscCall(VecCopy(x, tmp)); 4055 PetscCall(MatSolve(mat, b, x)); 4056 PetscCall(VecAXPY(x, one, tmp)); 4057 PetscCall(VecDestroy(&tmp)); 4058 } 4059 } 4060 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4061 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4062 PetscFunctionReturn(PETSC_SUCCESS); 4063 } 4064 4065 /*@ 4066 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4067 4068 Neighbor-wise Collective 4069 4070 Input Parameters: 4071 + mat - the factored matrix 4072 - b - the right-hand-side vector 4073 4074 Output Parameter: 4075 . x - the result vector 4076 4077 Level: developer 4078 4079 Notes: 4080 The vectors `b` and `x` cannot be the same. I.e., one cannot 4081 call `MatSolveTranspose`(A,x,x). 4082 4083 Most users should employ the `KSP` interface for linear solvers 4084 instead of working directly with matrix algebra routines such as this. 4085 See, e.g., `KSPCreate()`. 4086 4087 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4088 @*/ 4089 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4090 { 4091 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4092 4093 PetscFunctionBegin; 4094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4095 PetscValidType(mat, 1); 4096 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4097 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4098 PetscCheckSameComm(mat, 1, b, 2); 4099 PetscCheckSameComm(mat, 1, x, 3); 4100 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4101 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); 4102 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); 4103 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4104 MatCheckPreallocated(mat, 1); 4105 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4106 PetscCall(VecFlag(x, mat->factorerrortype)); 4107 if (mat->factorerrortype) { 4108 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4109 } else { 4110 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4111 PetscCall((*f)(mat, b, x)); 4112 } 4113 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4114 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4115 PetscFunctionReturn(PETSC_SUCCESS); 4116 } 4117 4118 /*@ 4119 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4120 factored matrix. 4121 4122 Neighbor-wise Collective 4123 4124 Input Parameters: 4125 + mat - the factored matrix 4126 . b - the right-hand-side vector 4127 - y - the vector to be added to 4128 4129 Output Parameter: 4130 . x - the result vector 4131 4132 Level: developer 4133 4134 Note: 4135 The vectors `b` and `x` cannot be the same. I.e., one cannot 4136 call `MatSolveTransposeAdd`(A,x,y,x). 4137 4138 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4139 @*/ 4140 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4141 { 4142 PetscScalar one = 1.0; 4143 Vec tmp; 4144 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4145 4146 PetscFunctionBegin; 4147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4148 PetscValidType(mat, 1); 4149 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4150 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4151 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4152 PetscCheckSameComm(mat, 1, b, 2); 4153 PetscCheckSameComm(mat, 1, y, 3); 4154 PetscCheckSameComm(mat, 1, x, 4); 4155 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4156 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); 4157 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); 4158 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); 4159 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); 4160 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4161 MatCheckPreallocated(mat, 1); 4162 4163 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4164 PetscCall(VecFlag(x, mat->factorerrortype)); 4165 if (mat->factorerrortype) { 4166 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4167 } else if (f) { 4168 PetscCall((*f)(mat, b, y, x)); 4169 } else { 4170 /* do the solve then the add manually */ 4171 if (x != y) { 4172 PetscCall(MatSolveTranspose(mat, b, x)); 4173 PetscCall(VecAXPY(x, one, y)); 4174 } else { 4175 PetscCall(VecDuplicate(x, &tmp)); 4176 PetscCall(VecCopy(x, tmp)); 4177 PetscCall(MatSolveTranspose(mat, b, x)); 4178 PetscCall(VecAXPY(x, one, tmp)); 4179 PetscCall(VecDestroy(&tmp)); 4180 } 4181 } 4182 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4183 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4184 PetscFunctionReturn(PETSC_SUCCESS); 4185 } 4186 4187 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4188 /*@ 4189 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4190 4191 Neighbor-wise Collective 4192 4193 Input Parameters: 4194 + mat - the matrix 4195 . b - the right-hand side 4196 . omega - the relaxation factor 4197 . flag - flag indicating the type of SOR (see below) 4198 . shift - diagonal shift 4199 . its - the number of iterations 4200 - lits - the number of local iterations 4201 4202 Output Parameter: 4203 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4204 4205 SOR Flags: 4206 + `SOR_FORWARD_SWEEP` - forward SOR 4207 . `SOR_BACKWARD_SWEEP` - backward SOR 4208 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4209 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4210 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4211 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4212 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4213 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4214 upper/lower triangular part of matrix to 4215 vector (with omega) 4216 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4217 4218 Level: developer 4219 4220 Notes: 4221 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4222 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4223 on each processor. 4224 4225 Application programmers will not generally use `MatSOR()` directly, 4226 but instead will employ the `KSP`/`PC` interface. 4227 4228 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4229 4230 Most users should employ the `KSP` interface for linear solvers 4231 instead of working directly with matrix algebra routines such as this. 4232 See, e.g., `KSPCreate()`. 4233 4234 Vectors `x` and `b` CANNOT be the same 4235 4236 The flags are implemented as bitwise inclusive or operations. 4237 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4238 to specify a zero initial guess for SSOR. 4239 4240 Developer Note: 4241 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4242 4243 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4244 @*/ 4245 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4246 { 4247 PetscFunctionBegin; 4248 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4249 PetscValidType(mat, 1); 4250 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4251 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4252 PetscCheckSameComm(mat, 1, b, 2); 4253 PetscCheckSameComm(mat, 1, x, 8); 4254 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4255 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4256 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); 4257 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); 4258 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); 4259 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4260 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4261 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4262 4263 MatCheckPreallocated(mat, 1); 4264 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4265 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4266 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4267 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4268 PetscFunctionReturn(PETSC_SUCCESS); 4269 } 4270 4271 /* 4272 Default matrix copy routine. 4273 */ 4274 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4275 { 4276 PetscInt i, rstart = 0, rend = 0, nz; 4277 const PetscInt *cwork; 4278 const PetscScalar *vwork; 4279 4280 PetscFunctionBegin; 4281 if (B->assembled) PetscCall(MatZeroEntries(B)); 4282 if (str == SAME_NONZERO_PATTERN) { 4283 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4284 for (i = rstart; i < rend; i++) { 4285 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4286 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4287 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4288 } 4289 } else { 4290 PetscCall(MatAYPX(B, 0.0, A, str)); 4291 } 4292 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4293 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4294 PetscFunctionReturn(PETSC_SUCCESS); 4295 } 4296 4297 /*@ 4298 MatCopy - Copies a matrix to another matrix. 4299 4300 Collective 4301 4302 Input Parameters: 4303 + A - the matrix 4304 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4305 4306 Output Parameter: 4307 . B - where the copy is put 4308 4309 Level: intermediate 4310 4311 Notes: 4312 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4313 4314 `MatCopy()` copies the matrix entries of a matrix to another existing 4315 matrix (after first zeroing the second matrix). A related routine is 4316 `MatConvert()`, which first creates a new matrix and then copies the data. 4317 4318 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4319 @*/ 4320 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4321 { 4322 PetscInt i; 4323 4324 PetscFunctionBegin; 4325 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4326 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4327 PetscValidType(A, 1); 4328 PetscValidType(B, 2); 4329 PetscCheckSameComm(A, 1, B, 2); 4330 MatCheckPreallocated(B, 2); 4331 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4332 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4333 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, 4334 A->cmap->N, B->cmap->N); 4335 MatCheckPreallocated(A, 1); 4336 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4337 4338 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4339 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4340 else PetscCall(MatCopy_Basic(A, B, str)); 4341 4342 B->stencil.dim = A->stencil.dim; 4343 B->stencil.noc = A->stencil.noc; 4344 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4345 B->stencil.dims[i] = A->stencil.dims[i]; 4346 B->stencil.starts[i] = A->stencil.starts[i]; 4347 } 4348 4349 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4350 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4351 PetscFunctionReturn(PETSC_SUCCESS); 4352 } 4353 4354 /*@ 4355 MatConvert - Converts a matrix to another matrix, either of the same 4356 or different type. 4357 4358 Collective 4359 4360 Input Parameters: 4361 + mat - the matrix 4362 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4363 same type as the original matrix. 4364 - reuse - denotes if the destination matrix is to be created or reused. 4365 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 4366 `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). 4367 4368 Output Parameter: 4369 . M - pointer to place new matrix 4370 4371 Level: intermediate 4372 4373 Notes: 4374 `MatConvert()` first creates a new matrix and then copies the data from 4375 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4376 entries of one matrix to another already existing matrix context. 4377 4378 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4379 the MPI communicator of the generated matrix is always the same as the communicator 4380 of the input matrix. 4381 4382 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4383 @*/ 4384 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4385 { 4386 PetscBool sametype, issame, flg; 4387 PetscBool3 issymmetric, ishermitian; 4388 char convname[256], mtype[256]; 4389 Mat B; 4390 4391 PetscFunctionBegin; 4392 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4393 PetscValidType(mat, 1); 4394 PetscAssertPointer(M, 4); 4395 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4396 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4397 MatCheckPreallocated(mat, 1); 4398 4399 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4400 if (flg) newtype = mtype; 4401 4402 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4403 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4404 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4405 if (reuse == MAT_REUSE_MATRIX) { 4406 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4407 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4408 } 4409 4410 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4411 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4412 PetscFunctionReturn(PETSC_SUCCESS); 4413 } 4414 4415 /* Cache Mat options because some converters use MatHeaderReplace */ 4416 issymmetric = mat->symmetric; 4417 ishermitian = mat->hermitian; 4418 4419 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4420 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4421 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4422 } else { 4423 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4424 const char *prefix[3] = {"seq", "mpi", ""}; 4425 PetscInt i; 4426 /* 4427 Order of precedence: 4428 0) See if newtype is a superclass of the current matrix. 4429 1) See if a specialized converter is known to the current matrix. 4430 2) See if a specialized converter is known to the desired matrix class. 4431 3) See if a good general converter is registered for the desired class 4432 (as of 6/27/03 only MATMPIADJ falls into this category). 4433 4) See if a good general converter is known for the current matrix. 4434 5) Use a really basic converter. 4435 */ 4436 4437 /* 0) See if newtype is a superclass of the current matrix. 4438 i.e mat is mpiaij and newtype is aij */ 4439 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4440 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4441 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4442 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4443 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4444 if (flg) { 4445 if (reuse == MAT_INPLACE_MATRIX) { 4446 PetscCall(PetscInfo(mat, "Early return\n")); 4447 PetscFunctionReturn(PETSC_SUCCESS); 4448 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4449 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4450 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4451 PetscFunctionReturn(PETSC_SUCCESS); 4452 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4453 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4454 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4455 PetscFunctionReturn(PETSC_SUCCESS); 4456 } 4457 } 4458 } 4459 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4460 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4461 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4462 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4463 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4464 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4465 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4466 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4467 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4468 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4469 if (conv) goto foundconv; 4470 } 4471 4472 /* 2) See if a specialized converter is known to the desired matrix class. */ 4473 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4474 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4475 PetscCall(MatSetType(B, newtype)); 4476 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4477 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4478 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4479 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4480 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4481 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4482 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4483 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4484 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4485 if (conv) { 4486 PetscCall(MatDestroy(&B)); 4487 goto foundconv; 4488 } 4489 } 4490 4491 /* 3) See if a good general converter is registered for the desired class */ 4492 conv = B->ops->convertfrom; 4493 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4494 PetscCall(MatDestroy(&B)); 4495 if (conv) goto foundconv; 4496 4497 /* 4) See if a good general converter is known for the current matrix */ 4498 if (mat->ops->convert) conv = mat->ops->convert; 4499 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4500 if (conv) goto foundconv; 4501 4502 /* 5) Use a really basic converter. */ 4503 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4504 conv = MatConvert_Basic; 4505 4506 foundconv: 4507 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4508 PetscCall((*conv)(mat, newtype, reuse, M)); 4509 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4510 /* the block sizes must be same if the mappings are copied over */ 4511 (*M)->rmap->bs = mat->rmap->bs; 4512 (*M)->cmap->bs = mat->cmap->bs; 4513 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4514 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4515 (*M)->rmap->mapping = mat->rmap->mapping; 4516 (*M)->cmap->mapping = mat->cmap->mapping; 4517 } 4518 (*M)->stencil.dim = mat->stencil.dim; 4519 (*M)->stencil.noc = mat->stencil.noc; 4520 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4521 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4522 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4523 } 4524 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4525 } 4526 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4527 4528 /* Copy Mat options */ 4529 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4530 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4531 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4532 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4533 PetscFunctionReturn(PETSC_SUCCESS); 4534 } 4535 4536 /*@ 4537 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4538 4539 Not Collective 4540 4541 Input Parameter: 4542 . mat - the matrix, must be a factored matrix 4543 4544 Output Parameter: 4545 . type - the string name of the package (do not free this string) 4546 4547 Level: intermediate 4548 4549 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4550 @*/ 4551 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4552 { 4553 PetscErrorCode (*conv)(Mat, MatSolverType *); 4554 4555 PetscFunctionBegin; 4556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4557 PetscValidType(mat, 1); 4558 PetscAssertPointer(type, 2); 4559 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4560 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4561 if (conv) PetscCall((*conv)(mat, type)); 4562 else *type = MATSOLVERPETSC; 4563 PetscFunctionReturn(PETSC_SUCCESS); 4564 } 4565 4566 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4567 struct _MatSolverTypeForSpecifcType { 4568 MatType mtype; 4569 /* no entry for MAT_FACTOR_NONE */ 4570 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4571 MatSolverTypeForSpecifcType next; 4572 }; 4573 4574 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4575 struct _MatSolverTypeHolder { 4576 char *name; 4577 MatSolverTypeForSpecifcType handlers; 4578 MatSolverTypeHolder next; 4579 }; 4580 4581 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4582 4583 /*@C 4584 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4585 4586 Logically Collective, No Fortran Support 4587 4588 Input Parameters: 4589 + package - name of the package, for example `petsc` or `superlu` 4590 . mtype - the matrix type that works with this package 4591 . ftype - the type of factorization supported by the package 4592 - createfactor - routine that will create the factored matrix ready to be used 4593 4594 Level: developer 4595 4596 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4597 `MatGetFactor()` 4598 @*/ 4599 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4600 { 4601 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4602 PetscBool flg; 4603 MatSolverTypeForSpecifcType inext, iprev = NULL; 4604 4605 PetscFunctionBegin; 4606 PetscCall(MatInitializePackage()); 4607 if (!next) { 4608 PetscCall(PetscNew(&MatSolverTypeHolders)); 4609 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4610 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4611 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4612 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4613 PetscFunctionReturn(PETSC_SUCCESS); 4614 } 4615 while (next) { 4616 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4617 if (flg) { 4618 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4619 inext = next->handlers; 4620 while (inext) { 4621 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4622 if (flg) { 4623 inext->createfactor[(int)ftype - 1] = createfactor; 4624 PetscFunctionReturn(PETSC_SUCCESS); 4625 } 4626 iprev = inext; 4627 inext = inext->next; 4628 } 4629 PetscCall(PetscNew(&iprev->next)); 4630 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4631 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4632 PetscFunctionReturn(PETSC_SUCCESS); 4633 } 4634 prev = next; 4635 next = next->next; 4636 } 4637 PetscCall(PetscNew(&prev->next)); 4638 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4639 PetscCall(PetscNew(&prev->next->handlers)); 4640 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4641 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4642 PetscFunctionReturn(PETSC_SUCCESS); 4643 } 4644 4645 /*@C 4646 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4647 4648 Input Parameters: 4649 + 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 4650 . ftype - the type of factorization supported by the type 4651 - mtype - the matrix type that works with this type 4652 4653 Output Parameters: 4654 + foundtype - `PETSC_TRUE` if the type was registered 4655 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4656 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4657 4658 Calling sequence of `createfactor`: 4659 + A - the matrix providing the factor matrix 4660 . ftype - the `MatFactorType` of the factor requested 4661 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4662 4663 Level: developer 4664 4665 Note: 4666 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4667 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4668 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4669 4670 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4671 `MatInitializePackage()` 4672 @*/ 4673 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4674 { 4675 MatSolverTypeHolder next = MatSolverTypeHolders; 4676 PetscBool flg; 4677 MatSolverTypeForSpecifcType inext; 4678 4679 PetscFunctionBegin; 4680 if (foundtype) *foundtype = PETSC_FALSE; 4681 if (foundmtype) *foundmtype = PETSC_FALSE; 4682 if (createfactor) *createfactor = NULL; 4683 4684 if (type) { 4685 while (next) { 4686 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4687 if (flg) { 4688 if (foundtype) *foundtype = PETSC_TRUE; 4689 inext = next->handlers; 4690 while (inext) { 4691 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4692 if (flg) { 4693 if (foundmtype) *foundmtype = PETSC_TRUE; 4694 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4695 PetscFunctionReturn(PETSC_SUCCESS); 4696 } 4697 inext = inext->next; 4698 } 4699 } 4700 next = next->next; 4701 } 4702 } else { 4703 while (next) { 4704 inext = next->handlers; 4705 while (inext) { 4706 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4707 if (flg && inext->createfactor[(int)ftype - 1]) { 4708 if (foundtype) *foundtype = PETSC_TRUE; 4709 if (foundmtype) *foundmtype = PETSC_TRUE; 4710 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4711 PetscFunctionReturn(PETSC_SUCCESS); 4712 } 4713 inext = inext->next; 4714 } 4715 next = next->next; 4716 } 4717 /* try with base classes inext->mtype */ 4718 next = MatSolverTypeHolders; 4719 while (next) { 4720 inext = next->handlers; 4721 while (inext) { 4722 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4723 if (flg && inext->createfactor[(int)ftype - 1]) { 4724 if (foundtype) *foundtype = PETSC_TRUE; 4725 if (foundmtype) *foundmtype = PETSC_TRUE; 4726 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4727 PetscFunctionReturn(PETSC_SUCCESS); 4728 } 4729 inext = inext->next; 4730 } 4731 next = next->next; 4732 } 4733 } 4734 PetscFunctionReturn(PETSC_SUCCESS); 4735 } 4736 4737 PetscErrorCode MatSolverTypeDestroy(void) 4738 { 4739 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4740 MatSolverTypeForSpecifcType inext, iprev; 4741 4742 PetscFunctionBegin; 4743 while (next) { 4744 PetscCall(PetscFree(next->name)); 4745 inext = next->handlers; 4746 while (inext) { 4747 PetscCall(PetscFree(inext->mtype)); 4748 iprev = inext; 4749 inext = inext->next; 4750 PetscCall(PetscFree(iprev)); 4751 } 4752 prev = next; 4753 next = next->next; 4754 PetscCall(PetscFree(prev)); 4755 } 4756 MatSolverTypeHolders = NULL; 4757 PetscFunctionReturn(PETSC_SUCCESS); 4758 } 4759 4760 /*@ 4761 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4762 4763 Logically Collective 4764 4765 Input Parameter: 4766 . mat - the matrix 4767 4768 Output Parameter: 4769 . flg - `PETSC_TRUE` if uses the ordering 4770 4771 Level: developer 4772 4773 Note: 4774 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4775 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4776 4777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4778 @*/ 4779 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4780 { 4781 PetscFunctionBegin; 4782 *flg = mat->canuseordering; 4783 PetscFunctionReturn(PETSC_SUCCESS); 4784 } 4785 4786 /*@ 4787 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4788 4789 Logically Collective 4790 4791 Input Parameters: 4792 + mat - the matrix obtained with `MatGetFactor()` 4793 - ftype - the factorization type to be used 4794 4795 Output Parameter: 4796 . otype - the preferred ordering type 4797 4798 Level: developer 4799 4800 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4801 @*/ 4802 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4803 { 4804 PetscFunctionBegin; 4805 *otype = mat->preferredordering[ftype]; 4806 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4807 PetscFunctionReturn(PETSC_SUCCESS); 4808 } 4809 4810 /*@ 4811 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4812 4813 Collective 4814 4815 Input Parameters: 4816 + mat - the matrix 4817 . 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 4818 the other criteria is returned 4819 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4820 4821 Output Parameter: 4822 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4823 4824 Options Database Keys: 4825 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4826 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4827 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4828 4829 Level: intermediate 4830 4831 Notes: 4832 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4833 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4834 4835 Users usually access the factorization solvers via `KSP` 4836 4837 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4838 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 4839 4840 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4841 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4842 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4843 4844 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4845 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4846 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4847 4848 Developer Note: 4849 This should actually be called `MatCreateFactor()` since it creates a new factor object 4850 4851 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4852 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4853 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4854 @*/ 4855 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4856 { 4857 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4858 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4859 4860 PetscFunctionBegin; 4861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4862 PetscValidType(mat, 1); 4863 4864 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4865 MatCheckPreallocated(mat, 1); 4866 4867 PetscCall(MatIsShell(mat, &shell)); 4868 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4869 if (hasop) { 4870 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4871 PetscFunctionReturn(PETSC_SUCCESS); 4872 } 4873 4874 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4875 if (!foundtype) { 4876 if (type) { 4877 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], 4878 ((PetscObject)mat)->type_name, type); 4879 } else { 4880 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); 4881 } 4882 } 4883 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4884 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); 4885 4886 PetscCall((*conv)(mat, ftype, f)); 4887 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4888 PetscFunctionReturn(PETSC_SUCCESS); 4889 } 4890 4891 /*@ 4892 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4893 4894 Not Collective 4895 4896 Input Parameters: 4897 + mat - the matrix 4898 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4899 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4900 4901 Output Parameter: 4902 . flg - PETSC_TRUE if the factorization is available 4903 4904 Level: intermediate 4905 4906 Notes: 4907 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4908 such as pastix, superlu, mumps etc. 4909 4910 PETSc must have been ./configure to use the external solver, using the option --download-package 4911 4912 Developer Note: 4913 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4914 4915 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4916 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4917 @*/ 4918 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4919 { 4920 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4921 4922 PetscFunctionBegin; 4923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4924 PetscAssertPointer(flg, 4); 4925 4926 *flg = PETSC_FALSE; 4927 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4928 4929 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4930 MatCheckPreallocated(mat, 1); 4931 4932 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4933 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4934 PetscFunctionReturn(PETSC_SUCCESS); 4935 } 4936 4937 /*@ 4938 MatDuplicate - Duplicates a matrix including the non-zero structure. 4939 4940 Collective 4941 4942 Input Parameters: 4943 + mat - the matrix 4944 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4945 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4946 4947 Output Parameter: 4948 . M - pointer to place new matrix 4949 4950 Level: intermediate 4951 4952 Notes: 4953 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4954 4955 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4956 4957 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. 4958 4959 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4960 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4961 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4962 4963 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4964 @*/ 4965 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4966 { 4967 Mat B; 4968 VecType vtype; 4969 PetscInt i; 4970 PetscObject dm, container_h, container_d; 4971 void (*viewf)(void); 4972 4973 PetscFunctionBegin; 4974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4975 PetscValidType(mat, 1); 4976 PetscAssertPointer(M, 3); 4977 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4978 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4979 MatCheckPreallocated(mat, 1); 4980 4981 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4982 PetscUseTypeMethod(mat, duplicate, op, M); 4983 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4984 B = *M; 4985 4986 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4987 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4988 PetscCall(MatGetVecType(mat, &vtype)); 4989 PetscCall(MatSetVecType(B, vtype)); 4990 4991 B->stencil.dim = mat->stencil.dim; 4992 B->stencil.noc = mat->stencil.noc; 4993 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4994 B->stencil.dims[i] = mat->stencil.dims[i]; 4995 B->stencil.starts[i] = mat->stencil.starts[i]; 4996 } 4997 4998 B->nooffproczerorows = mat->nooffproczerorows; 4999 B->nooffprocentries = mat->nooffprocentries; 5000 5001 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5002 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5003 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5004 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5005 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5006 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5007 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5008 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5009 PetscFunctionReturn(PETSC_SUCCESS); 5010 } 5011 5012 /*@ 5013 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5014 5015 Logically Collective 5016 5017 Input Parameter: 5018 . mat - the matrix 5019 5020 Output Parameter: 5021 . v - the diagonal of the matrix 5022 5023 Level: intermediate 5024 5025 Note: 5026 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5027 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5028 is larger than `ndiag`, the values of the remaining entries are unspecified. 5029 5030 Currently only correct in parallel for square matrices. 5031 5032 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5033 @*/ 5034 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5035 { 5036 PetscFunctionBegin; 5037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5038 PetscValidType(mat, 1); 5039 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5040 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5041 MatCheckPreallocated(mat, 1); 5042 if (PetscDefined(USE_DEBUG)) { 5043 PetscInt nv, row, col, ndiag; 5044 5045 PetscCall(VecGetLocalSize(v, &nv)); 5046 PetscCall(MatGetLocalSize(mat, &row, &col)); 5047 ndiag = PetscMin(row, col); 5048 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); 5049 } 5050 5051 PetscUseTypeMethod(mat, getdiagonal, v); 5052 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5053 PetscFunctionReturn(PETSC_SUCCESS); 5054 } 5055 5056 /*@ 5057 MatGetRowMin - Gets the minimum value (of the real part) of each 5058 row of the matrix 5059 5060 Logically Collective 5061 5062 Input Parameter: 5063 . mat - the matrix 5064 5065 Output Parameters: 5066 + v - the vector for storing the maximums 5067 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5068 5069 Level: intermediate 5070 5071 Note: 5072 The result of this call are the same as if one converted the matrix to dense format 5073 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5074 5075 This code is only implemented for a couple of matrix formats. 5076 5077 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5078 `MatGetRowMax()` 5079 @*/ 5080 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5081 { 5082 PetscFunctionBegin; 5083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5084 PetscValidType(mat, 1); 5085 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5086 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5087 5088 if (!mat->cmap->N) { 5089 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5090 if (idx) { 5091 PetscInt i, m = mat->rmap->n; 5092 for (i = 0; i < m; i++) idx[i] = -1; 5093 } 5094 } else { 5095 MatCheckPreallocated(mat, 1); 5096 } 5097 PetscUseTypeMethod(mat, getrowmin, v, idx); 5098 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5099 PetscFunctionReturn(PETSC_SUCCESS); 5100 } 5101 5102 /*@ 5103 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5104 row of the matrix 5105 5106 Logically Collective 5107 5108 Input Parameter: 5109 . mat - the matrix 5110 5111 Output Parameters: 5112 + v - the vector for storing the minimums 5113 - idx - the indices of the column found for each row (or `NULL` if not needed) 5114 5115 Level: intermediate 5116 5117 Notes: 5118 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5119 row is 0 (the first column). 5120 5121 This code is only implemented for a couple of matrix formats. 5122 5123 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5124 @*/ 5125 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5126 { 5127 PetscFunctionBegin; 5128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5129 PetscValidType(mat, 1); 5130 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5131 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5132 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5133 5134 if (!mat->cmap->N) { 5135 PetscCall(VecSet(v, 0.0)); 5136 if (idx) { 5137 PetscInt i, m = mat->rmap->n; 5138 for (i = 0; i < m; i++) idx[i] = -1; 5139 } 5140 } else { 5141 MatCheckPreallocated(mat, 1); 5142 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5143 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5144 } 5145 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5146 PetscFunctionReturn(PETSC_SUCCESS); 5147 } 5148 5149 /*@ 5150 MatGetRowMax - Gets the maximum value (of the real part) of each 5151 row of the matrix 5152 5153 Logically Collective 5154 5155 Input Parameter: 5156 . mat - the matrix 5157 5158 Output Parameters: 5159 + v - the vector for storing the maximums 5160 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5161 5162 Level: intermediate 5163 5164 Notes: 5165 The result of this call are the same as if one converted the matrix to dense format 5166 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5167 5168 This code is only implemented for a couple of matrix formats. 5169 5170 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5171 @*/ 5172 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5173 { 5174 PetscFunctionBegin; 5175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5176 PetscValidType(mat, 1); 5177 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5178 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5179 5180 if (!mat->cmap->N) { 5181 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5182 if (idx) { 5183 PetscInt i, m = mat->rmap->n; 5184 for (i = 0; i < m; i++) idx[i] = -1; 5185 } 5186 } else { 5187 MatCheckPreallocated(mat, 1); 5188 PetscUseTypeMethod(mat, getrowmax, v, idx); 5189 } 5190 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5191 PetscFunctionReturn(PETSC_SUCCESS); 5192 } 5193 5194 /*@ 5195 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5196 row of the matrix 5197 5198 Logically Collective 5199 5200 Input Parameter: 5201 . mat - the matrix 5202 5203 Output Parameters: 5204 + v - the vector for storing the maximums 5205 - idx - the indices of the column found for each row (or `NULL` if not needed) 5206 5207 Level: intermediate 5208 5209 Notes: 5210 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5211 row is 0 (the first column). 5212 5213 This code is only implemented for a couple of matrix formats. 5214 5215 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5216 @*/ 5217 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5218 { 5219 PetscFunctionBegin; 5220 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5221 PetscValidType(mat, 1); 5222 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5223 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5224 5225 if (!mat->cmap->N) { 5226 PetscCall(VecSet(v, 0.0)); 5227 if (idx) { 5228 PetscInt i, m = mat->rmap->n; 5229 for (i = 0; i < m; i++) idx[i] = -1; 5230 } 5231 } else { 5232 MatCheckPreallocated(mat, 1); 5233 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5234 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5235 } 5236 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5237 PetscFunctionReturn(PETSC_SUCCESS); 5238 } 5239 5240 /*@ 5241 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5242 5243 Logically Collective 5244 5245 Input Parameter: 5246 . mat - the matrix 5247 5248 Output Parameter: 5249 . v - the vector for storing the sum 5250 5251 Level: intermediate 5252 5253 This code is only implemented for a couple of matrix formats. 5254 5255 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5256 @*/ 5257 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5258 { 5259 PetscFunctionBegin; 5260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5261 PetscValidType(mat, 1); 5262 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5263 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5264 5265 if (!mat->cmap->N) { 5266 PetscCall(VecSet(v, 0.0)); 5267 } else { 5268 MatCheckPreallocated(mat, 1); 5269 PetscUseTypeMethod(mat, getrowsumabs, v); 5270 } 5271 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5272 PetscFunctionReturn(PETSC_SUCCESS); 5273 } 5274 5275 /*@ 5276 MatGetRowSum - Gets the sum of each row of the matrix 5277 5278 Logically or Neighborhood Collective 5279 5280 Input Parameter: 5281 . mat - the matrix 5282 5283 Output Parameter: 5284 . v - the vector for storing the sum of rows 5285 5286 Level: intermediate 5287 5288 Note: 5289 This code is slow since it is not currently specialized for different formats 5290 5291 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5292 @*/ 5293 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5294 { 5295 Vec ones; 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 MatCheckPreallocated(mat, 1); 5303 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5304 PetscCall(VecSet(ones, 1.)); 5305 PetscCall(MatMult(mat, ones, v)); 5306 PetscCall(VecDestroy(&ones)); 5307 PetscFunctionReturn(PETSC_SUCCESS); 5308 } 5309 5310 /*@ 5311 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5312 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5313 5314 Collective 5315 5316 Input Parameter: 5317 . mat - the matrix to provide the transpose 5318 5319 Output Parameter: 5320 . 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 5321 5322 Level: advanced 5323 5324 Note: 5325 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 5326 routine allows bypassing that call. 5327 5328 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5329 @*/ 5330 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5331 { 5332 MatParentState *rb = NULL; 5333 5334 PetscFunctionBegin; 5335 PetscCall(PetscNew(&rb)); 5336 rb->id = ((PetscObject)mat)->id; 5337 rb->state = 0; 5338 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5339 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5340 PetscFunctionReturn(PETSC_SUCCESS); 5341 } 5342 5343 /*@ 5344 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5345 5346 Collective 5347 5348 Input Parameters: 5349 + mat - the matrix to transpose 5350 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5351 5352 Output Parameter: 5353 . B - the transpose of the matrix 5354 5355 Level: intermediate 5356 5357 Notes: 5358 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5359 5360 `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 5361 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5362 5363 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. 5364 5365 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5366 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5367 5368 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5369 5370 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5371 5372 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5373 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5374 @*/ 5375 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5376 { 5377 PetscContainer rB = NULL; 5378 MatParentState *rb = NULL; 5379 5380 PetscFunctionBegin; 5381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5382 PetscValidType(mat, 1); 5383 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5384 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5385 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5386 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5387 MatCheckPreallocated(mat, 1); 5388 if (reuse == MAT_REUSE_MATRIX) { 5389 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5390 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5391 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5392 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5393 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5394 } 5395 5396 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5397 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5398 PetscUseTypeMethod(mat, transpose, reuse, B); 5399 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5400 } 5401 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5402 5403 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5404 if (reuse != MAT_INPLACE_MATRIX) { 5405 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5406 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5407 rb->state = ((PetscObject)mat)->state; 5408 rb->nonzerostate = mat->nonzerostate; 5409 } 5410 PetscFunctionReturn(PETSC_SUCCESS); 5411 } 5412 5413 /*@ 5414 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5415 5416 Collective 5417 5418 Input Parameter: 5419 . A - the matrix to transpose 5420 5421 Output Parameter: 5422 . 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 5423 numerical portion. 5424 5425 Level: intermediate 5426 5427 Note: 5428 This is not supported for many matrix types, use `MatTranspose()` in those cases 5429 5430 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5431 @*/ 5432 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5433 { 5434 PetscFunctionBegin; 5435 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5436 PetscValidType(A, 1); 5437 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5438 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5439 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5440 PetscUseTypeMethod(A, transposesymbolic, B); 5441 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5442 5443 PetscCall(MatTransposeSetPrecursor(A, *B)); 5444 PetscFunctionReturn(PETSC_SUCCESS); 5445 } 5446 5447 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5448 { 5449 PetscContainer rB; 5450 MatParentState *rb; 5451 5452 PetscFunctionBegin; 5453 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5454 PetscValidType(A, 1); 5455 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5456 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5457 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5458 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5459 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5460 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5461 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5462 PetscFunctionReturn(PETSC_SUCCESS); 5463 } 5464 5465 /*@ 5466 MatIsTranspose - Test whether a matrix is another one's transpose, 5467 or its own, in which case it tests symmetry. 5468 5469 Collective 5470 5471 Input Parameters: 5472 + A - the matrix to test 5473 . B - the matrix to test against, this can equal the first parameter 5474 - tol - tolerance, differences between entries smaller than this are counted as zero 5475 5476 Output Parameter: 5477 . flg - the result 5478 5479 Level: intermediate 5480 5481 Notes: 5482 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5483 test involves parallel copies of the block off-diagonal parts of the matrix. 5484 5485 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5486 @*/ 5487 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5488 { 5489 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5490 5491 PetscFunctionBegin; 5492 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5493 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5494 PetscAssertPointer(flg, 4); 5495 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5496 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5497 *flg = PETSC_FALSE; 5498 if (f && g) { 5499 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5500 PetscCall((*f)(A, B, tol, flg)); 5501 } else { 5502 MatType mattype; 5503 5504 PetscCall(MatGetType(f ? B : A, &mattype)); 5505 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5506 } 5507 PetscFunctionReturn(PETSC_SUCCESS); 5508 } 5509 5510 /*@ 5511 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5512 5513 Collective 5514 5515 Input Parameters: 5516 + mat - the matrix to transpose and complex conjugate 5517 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5518 5519 Output Parameter: 5520 . B - the Hermitian transpose 5521 5522 Level: intermediate 5523 5524 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5525 @*/ 5526 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5527 { 5528 PetscFunctionBegin; 5529 PetscCall(MatTranspose(mat, reuse, B)); 5530 #if defined(PETSC_USE_COMPLEX) 5531 PetscCall(MatConjugate(*B)); 5532 #endif 5533 PetscFunctionReturn(PETSC_SUCCESS); 5534 } 5535 5536 /*@ 5537 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5538 5539 Collective 5540 5541 Input Parameters: 5542 + A - the matrix to test 5543 . B - the matrix to test against, this can equal the first parameter 5544 - tol - tolerance, differences between entries smaller than this are counted as zero 5545 5546 Output Parameter: 5547 . flg - the result 5548 5549 Level: intermediate 5550 5551 Notes: 5552 Only available for `MATAIJ` matrices. 5553 5554 The sequential algorithm 5555 has a running time of the order of the number of nonzeros; the parallel 5556 test involves parallel copies of the block off-diagonal parts of the matrix. 5557 5558 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5559 @*/ 5560 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5561 { 5562 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5563 5564 PetscFunctionBegin; 5565 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5566 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5567 PetscAssertPointer(flg, 4); 5568 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5569 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5570 if (f && g) { 5571 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5572 PetscCall((*f)(A, B, tol, flg)); 5573 } 5574 PetscFunctionReturn(PETSC_SUCCESS); 5575 } 5576 5577 /*@ 5578 MatPermute - Creates a new matrix with rows and columns permuted from the 5579 original. 5580 5581 Collective 5582 5583 Input Parameters: 5584 + mat - the matrix to permute 5585 . row - row permutation, each processor supplies only the permutation for its rows 5586 - col - column permutation, each processor supplies only the permutation for its columns 5587 5588 Output Parameter: 5589 . B - the permuted matrix 5590 5591 Level: advanced 5592 5593 Note: 5594 The index sets map from row/col of permuted matrix to row/col of original matrix. 5595 The index sets should be on the same communicator as mat and have the same local sizes. 5596 5597 Developer Note: 5598 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5599 exploit the fact that row and col are permutations, consider implementing the 5600 more general `MatCreateSubMatrix()` instead. 5601 5602 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5603 @*/ 5604 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5605 { 5606 PetscFunctionBegin; 5607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5608 PetscValidType(mat, 1); 5609 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5610 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5611 PetscAssertPointer(B, 4); 5612 PetscCheckSameComm(mat, 1, row, 2); 5613 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5614 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5615 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5616 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5617 MatCheckPreallocated(mat, 1); 5618 5619 if (mat->ops->permute) { 5620 PetscUseTypeMethod(mat, permute, row, col, B); 5621 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5622 } else { 5623 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5624 } 5625 PetscFunctionReturn(PETSC_SUCCESS); 5626 } 5627 5628 /*@ 5629 MatEqual - Compares two matrices. 5630 5631 Collective 5632 5633 Input Parameters: 5634 + A - the first matrix 5635 - B - the second matrix 5636 5637 Output Parameter: 5638 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5639 5640 Level: intermediate 5641 5642 Note: 5643 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 5644 using several randomly created vectors, see `MatMultEqual()`. 5645 5646 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5647 @*/ 5648 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5649 { 5650 PetscFunctionBegin; 5651 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5652 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5653 PetscValidType(A, 1); 5654 PetscValidType(B, 2); 5655 PetscAssertPointer(flg, 3); 5656 PetscCheckSameComm(A, 1, B, 2); 5657 MatCheckPreallocated(A, 1); 5658 MatCheckPreallocated(B, 2); 5659 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5660 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5661 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, 5662 B->cmap->N); 5663 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5664 PetscUseTypeMethod(A, equal, B, flg); 5665 } else { 5666 PetscCall(MatMultEqual(A, B, 10, flg)); 5667 } 5668 PetscFunctionReturn(PETSC_SUCCESS); 5669 } 5670 5671 /*@ 5672 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5673 matrices that are stored as vectors. Either of the two scaling 5674 matrices can be `NULL`. 5675 5676 Collective 5677 5678 Input Parameters: 5679 + mat - the matrix to be scaled 5680 . l - the left scaling vector (or `NULL`) 5681 - r - the right scaling vector (or `NULL`) 5682 5683 Level: intermediate 5684 5685 Note: 5686 `MatDiagonalScale()` computes $A = LAR$, where 5687 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5688 The L scales the rows of the matrix, the R scales the columns of the matrix. 5689 5690 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5691 @*/ 5692 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5693 { 5694 PetscFunctionBegin; 5695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5696 PetscValidType(mat, 1); 5697 if (l) { 5698 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5699 PetscCheckSameComm(mat, 1, l, 2); 5700 } 5701 if (r) { 5702 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5703 PetscCheckSameComm(mat, 1, r, 3); 5704 } 5705 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5706 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5707 MatCheckPreallocated(mat, 1); 5708 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5709 5710 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5711 PetscUseTypeMethod(mat, diagonalscale, l, r); 5712 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5713 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5714 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5715 PetscFunctionReturn(PETSC_SUCCESS); 5716 } 5717 5718 /*@ 5719 MatScale - Scales all elements of a matrix by a given number. 5720 5721 Logically Collective 5722 5723 Input Parameters: 5724 + mat - the matrix to be scaled 5725 - a - the scaling value 5726 5727 Level: intermediate 5728 5729 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5730 @*/ 5731 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5732 { 5733 PetscFunctionBegin; 5734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5735 PetscValidType(mat, 1); 5736 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5737 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5738 PetscValidLogicalCollectiveScalar(mat, a, 2); 5739 MatCheckPreallocated(mat, 1); 5740 5741 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5742 if (a != (PetscScalar)1.0) { 5743 PetscUseTypeMethod(mat, scale, a); 5744 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5745 } 5746 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5747 PetscFunctionReturn(PETSC_SUCCESS); 5748 } 5749 5750 /*@ 5751 MatNorm - Calculates various norms of a matrix. 5752 5753 Collective 5754 5755 Input Parameters: 5756 + mat - the matrix 5757 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5758 5759 Output Parameter: 5760 . nrm - the resulting norm 5761 5762 Level: intermediate 5763 5764 .seealso: [](ch_matrices), `Mat` 5765 @*/ 5766 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5767 { 5768 PetscFunctionBegin; 5769 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5770 PetscValidType(mat, 1); 5771 PetscAssertPointer(nrm, 3); 5772 5773 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5774 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5775 MatCheckPreallocated(mat, 1); 5776 5777 PetscUseTypeMethod(mat, norm, type, nrm); 5778 PetscFunctionReturn(PETSC_SUCCESS); 5779 } 5780 5781 /* 5782 This variable is used to prevent counting of MatAssemblyBegin() that 5783 are called from within a MatAssemblyEnd(). 5784 */ 5785 static PetscInt MatAssemblyEnd_InUse = 0; 5786 /*@ 5787 MatAssemblyBegin - Begins assembling the matrix. This routine should 5788 be called after completing all calls to `MatSetValues()`. 5789 5790 Collective 5791 5792 Input Parameters: 5793 + mat - the matrix 5794 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5795 5796 Level: beginner 5797 5798 Notes: 5799 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5800 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5801 5802 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5803 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5804 using the matrix. 5805 5806 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5807 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 5808 a global collective operation requiring all processes that share the matrix. 5809 5810 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5811 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5812 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5813 5814 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5815 @*/ 5816 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5817 { 5818 PetscFunctionBegin; 5819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5820 PetscValidType(mat, 1); 5821 MatCheckPreallocated(mat, 1); 5822 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5823 if (mat->assembled) { 5824 mat->was_assembled = PETSC_TRUE; 5825 mat->assembled = PETSC_FALSE; 5826 } 5827 5828 if (!MatAssemblyEnd_InUse) { 5829 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5830 PetscTryTypeMethod(mat, assemblybegin, type); 5831 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5832 } else PetscTryTypeMethod(mat, assemblybegin, type); 5833 PetscFunctionReturn(PETSC_SUCCESS); 5834 } 5835 5836 /*@ 5837 MatAssembled - Indicates if a matrix has been assembled and is ready for 5838 use; for example, in matrix-vector product. 5839 5840 Not Collective 5841 5842 Input Parameter: 5843 . mat - the matrix 5844 5845 Output Parameter: 5846 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5847 5848 Level: advanced 5849 5850 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5851 @*/ 5852 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5853 { 5854 PetscFunctionBegin; 5855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5856 PetscAssertPointer(assembled, 2); 5857 *assembled = mat->assembled; 5858 PetscFunctionReturn(PETSC_SUCCESS); 5859 } 5860 5861 /*@ 5862 MatAssemblyEnd - Completes assembling the matrix. This routine should 5863 be called after `MatAssemblyBegin()`. 5864 5865 Collective 5866 5867 Input Parameters: 5868 + mat - the matrix 5869 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5870 5871 Options Database Keys: 5872 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5873 . -mat_view ::ascii_info_detail - Prints more detailed info 5874 . -mat_view - Prints matrix in ASCII format 5875 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5876 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5877 . -display <name> - Sets display name (default is host) 5878 . -draw_pause <sec> - Sets number of seconds to pause after display 5879 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5880 . -viewer_socket_machine <machine> - Machine to use for socket 5881 . -viewer_socket_port <port> - Port number to use for socket 5882 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5883 5884 Level: beginner 5885 5886 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5887 @*/ 5888 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5889 { 5890 static PetscInt inassm = 0; 5891 PetscBool flg = PETSC_FALSE; 5892 5893 PetscFunctionBegin; 5894 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5895 PetscValidType(mat, 1); 5896 5897 inassm++; 5898 MatAssemblyEnd_InUse++; 5899 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5900 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5901 PetscTryTypeMethod(mat, assemblyend, type); 5902 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5903 } else PetscTryTypeMethod(mat, assemblyend, type); 5904 5905 /* Flush assembly is not a true assembly */ 5906 if (type != MAT_FLUSH_ASSEMBLY) { 5907 if (mat->num_ass) { 5908 if (!mat->symmetry_eternal) { 5909 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5910 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5911 } 5912 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5913 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5914 } 5915 mat->num_ass++; 5916 mat->assembled = PETSC_TRUE; 5917 mat->ass_nonzerostate = mat->nonzerostate; 5918 } 5919 5920 mat->insertmode = NOT_SET_VALUES; 5921 MatAssemblyEnd_InUse--; 5922 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5923 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5924 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5925 5926 if (mat->checksymmetryonassembly) { 5927 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5928 if (flg) { 5929 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5930 } else { 5931 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5932 } 5933 } 5934 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5935 } 5936 inassm--; 5937 PetscFunctionReturn(PETSC_SUCCESS); 5938 } 5939 5940 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5941 /*@ 5942 MatSetOption - Sets a parameter option for a matrix. Some options 5943 may be specific to certain storage formats. Some options 5944 determine how values will be inserted (or added). Sorted, 5945 row-oriented input will generally assemble the fastest. The default 5946 is row-oriented. 5947 5948 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5949 5950 Input Parameters: 5951 + mat - the matrix 5952 . op - the option, one of those listed below (and possibly others), 5953 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5954 5955 Options Describing Matrix Structure: 5956 + `MAT_SPD` - symmetric positive definite 5957 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5958 . `MAT_HERMITIAN` - transpose is the complex conjugation 5959 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5960 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5961 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5962 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5963 5964 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5965 do not need to be computed (usually at a high cost) 5966 5967 Options For Use with `MatSetValues()`: 5968 Insert a logically dense subblock, which can be 5969 . `MAT_ROW_ORIENTED` - row-oriented (default) 5970 5971 These options reflect the data you pass in with `MatSetValues()`; it has 5972 nothing to do with how the data is stored internally in the matrix 5973 data structure. 5974 5975 When (re)assembling a matrix, we can restrict the input for 5976 efficiency/debugging purposes. These options include 5977 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5978 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5979 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5980 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5981 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5982 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5983 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5984 performance for very large process counts. 5985 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5986 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5987 functions, instead sending only neighbor messages. 5988 5989 Level: intermediate 5990 5991 Notes: 5992 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5993 5994 Some options are relevant only for particular matrix types and 5995 are thus ignored by others. Other options are not supported by 5996 certain matrix types and will generate an error message if set. 5997 5998 If using Fortran to compute a matrix, one may need to 5999 use the column-oriented option (or convert to the row-oriented 6000 format). 6001 6002 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6003 that would generate a new entry in the nonzero structure is instead 6004 ignored. Thus, if memory has not already been allocated for this particular 6005 data, then the insertion is ignored. For dense matrices, in which 6006 the entire array is allocated, no entries are ever ignored. 6007 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6008 6009 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6010 that would generate a new entry in the nonzero structure instead produces 6011 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 6012 6013 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6014 that would generate a new entry that has not been preallocated will 6015 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6016 only.) This is a useful flag when debugging matrix memory preallocation. 6017 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6018 6019 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6020 other processors should be dropped, rather than stashed. 6021 This is useful if you know that the "owning" processor is also 6022 always generating the correct matrix entries, so that PETSc need 6023 not transfer duplicate entries generated on another processor. 6024 6025 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6026 searches during matrix assembly. When this flag is set, the hash table 6027 is created during the first matrix assembly. This hash table is 6028 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6029 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6030 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6031 supported by `MATMPIBAIJ` format only. 6032 6033 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6034 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6035 6036 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6037 a zero location in the matrix 6038 6039 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6040 6041 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6042 zero row routines and thus improves performance for very large process counts. 6043 6044 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6045 part of the matrix (since they should match the upper triangular part). 6046 6047 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6048 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6049 with finite difference schemes with non-periodic boundary conditions. 6050 6051 Developer Note: 6052 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6053 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6054 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6055 not changed. 6056 6057 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6058 @*/ 6059 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6060 { 6061 PetscFunctionBegin; 6062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6063 if (op > 0) { 6064 PetscValidLogicalCollectiveEnum(mat, op, 2); 6065 PetscValidLogicalCollectiveBool(mat, flg, 3); 6066 } 6067 6068 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); 6069 6070 switch (op) { 6071 case MAT_FORCE_DIAGONAL_ENTRIES: 6072 mat->force_diagonals = flg; 6073 PetscFunctionReturn(PETSC_SUCCESS); 6074 case MAT_NO_OFF_PROC_ENTRIES: 6075 mat->nooffprocentries = flg; 6076 PetscFunctionReturn(PETSC_SUCCESS); 6077 case MAT_SUBSET_OFF_PROC_ENTRIES: 6078 mat->assembly_subset = flg; 6079 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6080 #if !defined(PETSC_HAVE_MPIUNI) 6081 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6082 #endif 6083 mat->stash.first_assembly_done = PETSC_FALSE; 6084 } 6085 PetscFunctionReturn(PETSC_SUCCESS); 6086 case MAT_NO_OFF_PROC_ZERO_ROWS: 6087 mat->nooffproczerorows = flg; 6088 PetscFunctionReturn(PETSC_SUCCESS); 6089 case MAT_SPD: 6090 if (flg) { 6091 mat->spd = PETSC_BOOL3_TRUE; 6092 mat->symmetric = PETSC_BOOL3_TRUE; 6093 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6094 } else { 6095 mat->spd = PETSC_BOOL3_FALSE; 6096 } 6097 break; 6098 case MAT_SYMMETRIC: 6099 mat->symmetric = PetscBoolToBool3(flg); 6100 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6101 #if !defined(PETSC_USE_COMPLEX) 6102 mat->hermitian = PetscBoolToBool3(flg); 6103 #endif 6104 break; 6105 case MAT_HERMITIAN: 6106 mat->hermitian = PetscBoolToBool3(flg); 6107 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6108 #if !defined(PETSC_USE_COMPLEX) 6109 mat->symmetric = PetscBoolToBool3(flg); 6110 #endif 6111 break; 6112 case MAT_STRUCTURALLY_SYMMETRIC: 6113 mat->structurally_symmetric = PetscBoolToBool3(flg); 6114 break; 6115 case MAT_SYMMETRY_ETERNAL: 6116 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"); 6117 mat->symmetry_eternal = flg; 6118 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6119 break; 6120 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6121 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"); 6122 mat->structural_symmetry_eternal = flg; 6123 break; 6124 case MAT_SPD_ETERNAL: 6125 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"); 6126 mat->spd_eternal = flg; 6127 if (flg) { 6128 mat->structural_symmetry_eternal = PETSC_TRUE; 6129 mat->symmetry_eternal = PETSC_TRUE; 6130 } 6131 break; 6132 case MAT_STRUCTURE_ONLY: 6133 mat->structure_only = flg; 6134 break; 6135 case MAT_SORTED_FULL: 6136 mat->sortedfull = flg; 6137 break; 6138 default: 6139 break; 6140 } 6141 PetscTryTypeMethod(mat, setoption, op, flg); 6142 PetscFunctionReturn(PETSC_SUCCESS); 6143 } 6144 6145 /*@ 6146 MatGetOption - Gets a parameter option that has been set for a matrix. 6147 6148 Logically Collective 6149 6150 Input Parameters: 6151 + mat - the matrix 6152 - op - the option, this only responds to certain options, check the code for which ones 6153 6154 Output Parameter: 6155 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6156 6157 Level: intermediate 6158 6159 Notes: 6160 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6161 6162 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6163 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6164 6165 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6166 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6167 @*/ 6168 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6169 { 6170 PetscFunctionBegin; 6171 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6172 PetscValidType(mat, 1); 6173 6174 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); 6175 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()"); 6176 6177 switch (op) { 6178 case MAT_NO_OFF_PROC_ENTRIES: 6179 *flg = mat->nooffprocentries; 6180 break; 6181 case MAT_NO_OFF_PROC_ZERO_ROWS: 6182 *flg = mat->nooffproczerorows; 6183 break; 6184 case MAT_SYMMETRIC: 6185 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6186 break; 6187 case MAT_HERMITIAN: 6188 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6189 break; 6190 case MAT_STRUCTURALLY_SYMMETRIC: 6191 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6192 break; 6193 case MAT_SPD: 6194 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6195 break; 6196 case MAT_SYMMETRY_ETERNAL: 6197 *flg = mat->symmetry_eternal; 6198 break; 6199 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6200 *flg = mat->symmetry_eternal; 6201 break; 6202 default: 6203 break; 6204 } 6205 PetscFunctionReturn(PETSC_SUCCESS); 6206 } 6207 6208 /*@ 6209 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6210 this routine retains the old nonzero structure. 6211 6212 Logically Collective 6213 6214 Input Parameter: 6215 . mat - the matrix 6216 6217 Level: intermediate 6218 6219 Note: 6220 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. 6221 See the Performance chapter of the users manual for information on preallocating matrices. 6222 6223 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6224 @*/ 6225 PetscErrorCode MatZeroEntries(Mat mat) 6226 { 6227 PetscFunctionBegin; 6228 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6229 PetscValidType(mat, 1); 6230 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6231 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"); 6232 MatCheckPreallocated(mat, 1); 6233 6234 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6235 PetscUseTypeMethod(mat, zeroentries); 6236 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6237 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6238 PetscFunctionReturn(PETSC_SUCCESS); 6239 } 6240 6241 /*@ 6242 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6243 of a set of rows and columns of a matrix. 6244 6245 Collective 6246 6247 Input Parameters: 6248 + mat - the matrix 6249 . numRows - the number of rows/columns to zero 6250 . rows - the global row indices 6251 . diag - value put in the diagonal of the eliminated rows 6252 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6253 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6254 6255 Level: intermediate 6256 6257 Notes: 6258 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6259 6260 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6261 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 6262 6263 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6264 Krylov method to take advantage of the known solution on the zeroed rows. 6265 6266 For the parallel case, all processes that share the matrix (i.e., 6267 those in the communicator used for matrix creation) MUST call this 6268 routine, regardless of whether any rows being zeroed are owned by 6269 them. 6270 6271 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6272 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 6273 missing. 6274 6275 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6276 list only rows local to itself). 6277 6278 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6279 6280 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6281 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6282 @*/ 6283 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6284 { 6285 PetscFunctionBegin; 6286 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6287 PetscValidType(mat, 1); 6288 if (numRows) PetscAssertPointer(rows, 3); 6289 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6290 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6291 MatCheckPreallocated(mat, 1); 6292 6293 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6294 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6295 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6296 PetscFunctionReturn(PETSC_SUCCESS); 6297 } 6298 6299 /*@ 6300 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6301 of a set of rows and columns of a matrix. 6302 6303 Collective 6304 6305 Input Parameters: 6306 + mat - the matrix 6307 . is - the rows to zero 6308 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6309 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6310 - b - optional vector of right-hand side, that will be adjusted by provided solution 6311 6312 Level: intermediate 6313 6314 Note: 6315 See `MatZeroRowsColumns()` for details on how this routine operates. 6316 6317 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6318 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6319 @*/ 6320 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6321 { 6322 PetscInt numRows; 6323 const PetscInt *rows; 6324 6325 PetscFunctionBegin; 6326 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6327 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6328 PetscValidType(mat, 1); 6329 PetscValidType(is, 2); 6330 PetscCall(ISGetLocalSize(is, &numRows)); 6331 PetscCall(ISGetIndices(is, &rows)); 6332 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6333 PetscCall(ISRestoreIndices(is, &rows)); 6334 PetscFunctionReturn(PETSC_SUCCESS); 6335 } 6336 6337 /*@ 6338 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6339 of a set of rows of a matrix. 6340 6341 Collective 6342 6343 Input Parameters: 6344 + mat - the matrix 6345 . numRows - the number of rows to zero 6346 . rows - the global row indices 6347 . diag - value put in the diagonal of the zeroed rows 6348 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6349 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6350 6351 Level: intermediate 6352 6353 Notes: 6354 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6355 6356 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6357 6358 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6359 Krylov method to take advantage of the known solution on the zeroed rows. 6360 6361 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) 6362 from the matrix. 6363 6364 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6365 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6366 formats this does not alter the nonzero structure. 6367 6368 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6369 of the matrix is not changed the values are 6370 merely zeroed. 6371 6372 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6373 formats can optionally remove the main diagonal entry from the 6374 nonzero structure as well, by passing 0.0 as the final argument). 6375 6376 For the parallel case, all processes that share the matrix (i.e., 6377 those in the communicator used for matrix creation) MUST call this 6378 routine, regardless of whether any rows being zeroed are owned by 6379 them. 6380 6381 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6382 list only rows local to itself). 6383 6384 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6385 owns that are to be zeroed. This saves a global synchronization in the implementation. 6386 6387 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6388 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6389 @*/ 6390 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6391 { 6392 PetscFunctionBegin; 6393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6394 PetscValidType(mat, 1); 6395 if (numRows) PetscAssertPointer(rows, 3); 6396 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6397 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6398 MatCheckPreallocated(mat, 1); 6399 6400 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6401 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6402 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6403 PetscFunctionReturn(PETSC_SUCCESS); 6404 } 6405 6406 /*@ 6407 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6408 of a set of rows of a matrix indicated by an `IS` 6409 6410 Collective 6411 6412 Input Parameters: 6413 + mat - the matrix 6414 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6415 . diag - value put in all diagonals of eliminated rows 6416 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6417 - b - optional vector of right-hand side, that will be adjusted by provided solution 6418 6419 Level: intermediate 6420 6421 Note: 6422 See `MatZeroRows()` for details on how this routine operates. 6423 6424 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6425 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6426 @*/ 6427 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6428 { 6429 PetscInt numRows = 0; 6430 const PetscInt *rows = NULL; 6431 6432 PetscFunctionBegin; 6433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6434 PetscValidType(mat, 1); 6435 if (is) { 6436 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6437 PetscCall(ISGetLocalSize(is, &numRows)); 6438 PetscCall(ISGetIndices(is, &rows)); 6439 } 6440 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6441 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6442 PetscFunctionReturn(PETSC_SUCCESS); 6443 } 6444 6445 /*@ 6446 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6447 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6448 6449 Collective 6450 6451 Input Parameters: 6452 + mat - the matrix 6453 . numRows - the number of rows to remove 6454 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6455 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6456 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6457 - b - optional vector of right-hand side, that will be adjusted by provided solution 6458 6459 Level: intermediate 6460 6461 Notes: 6462 See `MatZeroRows()` for details on how this routine operates. 6463 6464 The grid coordinates are across the entire grid, not just the local portion 6465 6466 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6467 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6468 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6469 `DM_BOUNDARY_PERIODIC` boundary type. 6470 6471 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 6472 a single value per point) you can skip filling those indices. 6473 6474 Fortran Note: 6475 `idxm` and `idxn` should be declared as 6476 .vb 6477 MatStencil idxm(4, m) 6478 .ve 6479 and the values inserted using 6480 .vb 6481 idxm(MatStencil_i, 1) = i 6482 idxm(MatStencil_j, 1) = j 6483 idxm(MatStencil_k, 1) = k 6484 idxm(MatStencil_c, 1) = c 6485 etc 6486 .ve 6487 6488 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6489 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6490 @*/ 6491 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6492 { 6493 PetscInt dim = mat->stencil.dim; 6494 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6495 PetscInt *dims = mat->stencil.dims + 1; 6496 PetscInt *starts = mat->stencil.starts; 6497 PetscInt *dxm = (PetscInt *)rows; 6498 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6499 6500 PetscFunctionBegin; 6501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6502 PetscValidType(mat, 1); 6503 if (numRows) PetscAssertPointer(rows, 3); 6504 6505 PetscCall(PetscMalloc1(numRows, &jdxm)); 6506 for (i = 0; i < numRows; ++i) { 6507 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6508 for (j = 0; j < 3 - sdim; ++j) dxm++; 6509 /* Local index in X dir */ 6510 tmp = *dxm++ - starts[0]; 6511 /* Loop over remaining dimensions */ 6512 for (j = 0; j < dim - 1; ++j) { 6513 /* If nonlocal, set index to be negative */ 6514 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6515 /* Update local index */ 6516 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6517 } 6518 /* Skip component slot if necessary */ 6519 if (mat->stencil.noc) dxm++; 6520 /* Local row number */ 6521 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6522 } 6523 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6524 PetscCall(PetscFree(jdxm)); 6525 PetscFunctionReturn(PETSC_SUCCESS); 6526 } 6527 6528 /*@ 6529 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6530 of a set of rows and columns of a matrix. 6531 6532 Collective 6533 6534 Input Parameters: 6535 + mat - the matrix 6536 . numRows - the number of rows/columns to remove 6537 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6538 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6539 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6540 - b - optional vector of right-hand side, that will be adjusted by provided solution 6541 6542 Level: intermediate 6543 6544 Notes: 6545 See `MatZeroRowsColumns()` for details on how this routine operates. 6546 6547 The grid coordinates are across the entire grid, not just the local portion 6548 6549 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6550 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6551 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6552 `DM_BOUNDARY_PERIODIC` boundary type. 6553 6554 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 6555 a single value per point) you can skip filling those indices. 6556 6557 Fortran Note: 6558 `idxm` and `idxn` should be declared as 6559 .vb 6560 MatStencil idxm(4, m) 6561 .ve 6562 and the values inserted using 6563 .vb 6564 idxm(MatStencil_i, 1) = i 6565 idxm(MatStencil_j, 1) = j 6566 idxm(MatStencil_k, 1) = k 6567 idxm(MatStencil_c, 1) = c 6568 etc 6569 .ve 6570 6571 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6572 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6573 @*/ 6574 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6575 { 6576 PetscInt dim = mat->stencil.dim; 6577 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6578 PetscInt *dims = mat->stencil.dims + 1; 6579 PetscInt *starts = mat->stencil.starts; 6580 PetscInt *dxm = (PetscInt *)rows; 6581 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6582 6583 PetscFunctionBegin; 6584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6585 PetscValidType(mat, 1); 6586 if (numRows) PetscAssertPointer(rows, 3); 6587 6588 PetscCall(PetscMalloc1(numRows, &jdxm)); 6589 for (i = 0; i < numRows; ++i) { 6590 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6591 for (j = 0; j < 3 - sdim; ++j) dxm++; 6592 /* Local index in X dir */ 6593 tmp = *dxm++ - starts[0]; 6594 /* Loop over remaining dimensions */ 6595 for (j = 0; j < dim - 1; ++j) { 6596 /* If nonlocal, set index to be negative */ 6597 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6598 /* Update local index */ 6599 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6600 } 6601 /* Skip component slot if necessary */ 6602 if (mat->stencil.noc) dxm++; 6603 /* Local row number */ 6604 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6605 } 6606 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6607 PetscCall(PetscFree(jdxm)); 6608 PetscFunctionReturn(PETSC_SUCCESS); 6609 } 6610 6611 /*@ 6612 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6613 of a set of rows of a matrix; using local numbering of rows. 6614 6615 Collective 6616 6617 Input Parameters: 6618 + mat - the matrix 6619 . numRows - the number of rows to remove 6620 . rows - the local row indices 6621 . diag - value put in all diagonals of eliminated rows 6622 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6623 - b - optional vector of right-hand side, that will be adjusted by provided solution 6624 6625 Level: intermediate 6626 6627 Notes: 6628 Before calling `MatZeroRowsLocal()`, the user must first set the 6629 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6630 6631 See `MatZeroRows()` for details on how this routine operates. 6632 6633 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6634 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6635 @*/ 6636 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6637 { 6638 PetscFunctionBegin; 6639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6640 PetscValidType(mat, 1); 6641 if (numRows) PetscAssertPointer(rows, 3); 6642 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6643 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6644 MatCheckPreallocated(mat, 1); 6645 6646 if (mat->ops->zerorowslocal) { 6647 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6648 } else { 6649 IS is, newis; 6650 const PetscInt *newRows; 6651 6652 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6653 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6654 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6655 PetscCall(ISGetIndices(newis, &newRows)); 6656 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6657 PetscCall(ISRestoreIndices(newis, &newRows)); 6658 PetscCall(ISDestroy(&newis)); 6659 PetscCall(ISDestroy(&is)); 6660 } 6661 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6662 PetscFunctionReturn(PETSC_SUCCESS); 6663 } 6664 6665 /*@ 6666 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6667 of a set of rows of a matrix; using local numbering of rows. 6668 6669 Collective 6670 6671 Input Parameters: 6672 + mat - the matrix 6673 . is - index set of rows to remove 6674 . diag - value put in all diagonals of eliminated rows 6675 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6676 - b - optional vector of right-hand side, that will be adjusted by provided solution 6677 6678 Level: intermediate 6679 6680 Notes: 6681 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6682 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6683 6684 See `MatZeroRows()` for details on how this routine operates. 6685 6686 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6687 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6688 @*/ 6689 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6690 { 6691 PetscInt numRows; 6692 const PetscInt *rows; 6693 6694 PetscFunctionBegin; 6695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6696 PetscValidType(mat, 1); 6697 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6698 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6699 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6700 MatCheckPreallocated(mat, 1); 6701 6702 PetscCall(ISGetLocalSize(is, &numRows)); 6703 PetscCall(ISGetIndices(is, &rows)); 6704 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6705 PetscCall(ISRestoreIndices(is, &rows)); 6706 PetscFunctionReturn(PETSC_SUCCESS); 6707 } 6708 6709 /*@ 6710 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6711 of a set of rows and columns of a matrix; using local numbering of rows. 6712 6713 Collective 6714 6715 Input Parameters: 6716 + mat - the matrix 6717 . numRows - the number of rows to remove 6718 . rows - the global row indices 6719 . diag - value put in all diagonals of eliminated rows 6720 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6721 - b - optional vector of right-hand side, that will be adjusted by provided solution 6722 6723 Level: intermediate 6724 6725 Notes: 6726 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6727 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6728 6729 See `MatZeroRowsColumns()` for details on how this routine operates. 6730 6731 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6732 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6733 @*/ 6734 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6735 { 6736 IS is, newis; 6737 const PetscInt *newRows; 6738 6739 PetscFunctionBegin; 6740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6741 PetscValidType(mat, 1); 6742 if (numRows) PetscAssertPointer(rows, 3); 6743 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6744 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6745 MatCheckPreallocated(mat, 1); 6746 6747 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6748 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6749 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6750 PetscCall(ISGetIndices(newis, &newRows)); 6751 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6752 PetscCall(ISRestoreIndices(newis, &newRows)); 6753 PetscCall(ISDestroy(&newis)); 6754 PetscCall(ISDestroy(&is)); 6755 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6756 PetscFunctionReturn(PETSC_SUCCESS); 6757 } 6758 6759 /*@ 6760 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6761 of a set of rows and columns of a matrix; using local numbering of rows. 6762 6763 Collective 6764 6765 Input Parameters: 6766 + mat - the matrix 6767 . is - index set of rows to remove 6768 . diag - value put in all diagonals of eliminated rows 6769 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6770 - b - optional vector of right-hand side, that will be adjusted by provided solution 6771 6772 Level: intermediate 6773 6774 Notes: 6775 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6776 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6777 6778 See `MatZeroRowsColumns()` for details on how this routine operates. 6779 6780 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6781 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6782 @*/ 6783 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6784 { 6785 PetscInt numRows; 6786 const PetscInt *rows; 6787 6788 PetscFunctionBegin; 6789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6790 PetscValidType(mat, 1); 6791 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6792 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6793 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6794 MatCheckPreallocated(mat, 1); 6795 6796 PetscCall(ISGetLocalSize(is, &numRows)); 6797 PetscCall(ISGetIndices(is, &rows)); 6798 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6799 PetscCall(ISRestoreIndices(is, &rows)); 6800 PetscFunctionReturn(PETSC_SUCCESS); 6801 } 6802 6803 /*@ 6804 MatGetSize - Returns the numbers of rows and columns in a matrix. 6805 6806 Not Collective 6807 6808 Input Parameter: 6809 . mat - the matrix 6810 6811 Output Parameters: 6812 + m - the number of global rows 6813 - n - the number of global columns 6814 6815 Level: beginner 6816 6817 Note: 6818 Both output parameters can be `NULL` on input. 6819 6820 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6821 @*/ 6822 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6823 { 6824 PetscFunctionBegin; 6825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6826 if (m) *m = mat->rmap->N; 6827 if (n) *n = mat->cmap->N; 6828 PetscFunctionReturn(PETSC_SUCCESS); 6829 } 6830 6831 /*@ 6832 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6833 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6834 6835 Not Collective 6836 6837 Input Parameter: 6838 . mat - the matrix 6839 6840 Output Parameters: 6841 + m - the number of local rows, use `NULL` to not obtain this value 6842 - n - the number of local columns, use `NULL` to not obtain this value 6843 6844 Level: beginner 6845 6846 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6847 @*/ 6848 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6849 { 6850 PetscFunctionBegin; 6851 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6852 if (m) PetscAssertPointer(m, 2); 6853 if (n) PetscAssertPointer(n, 3); 6854 if (m) *m = mat->rmap->n; 6855 if (n) *n = mat->cmap->n; 6856 PetscFunctionReturn(PETSC_SUCCESS); 6857 } 6858 6859 /*@ 6860 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6861 vector one multiplies this matrix by that are owned by this processor. 6862 6863 Not Collective, unless matrix has not been allocated, then collective 6864 6865 Input Parameter: 6866 . mat - the matrix 6867 6868 Output Parameters: 6869 + m - the global index of the first local column, use `NULL` to not obtain this value 6870 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6871 6872 Level: developer 6873 6874 Notes: 6875 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6876 6877 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6878 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6879 6880 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6881 the local values in the matrix. 6882 6883 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6884 Layouts](sec_matlayout) for details on matrix layouts. 6885 6886 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6887 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6888 @*/ 6889 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6890 { 6891 PetscFunctionBegin; 6892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6893 PetscValidType(mat, 1); 6894 if (m) PetscAssertPointer(m, 2); 6895 if (n) PetscAssertPointer(n, 3); 6896 MatCheckPreallocated(mat, 1); 6897 if (m) *m = mat->cmap->rstart; 6898 if (n) *n = mat->cmap->rend; 6899 PetscFunctionReturn(PETSC_SUCCESS); 6900 } 6901 6902 /*@ 6903 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6904 this MPI process. 6905 6906 Not Collective 6907 6908 Input Parameter: 6909 . mat - the matrix 6910 6911 Output Parameters: 6912 + m - the global index of the first local row, use `NULL` to not obtain this value 6913 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6914 6915 Level: beginner 6916 6917 Notes: 6918 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6919 6920 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6921 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6922 6923 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6924 the local values in the matrix. 6925 6926 The high argument is one more than the last element stored locally. 6927 6928 For all matrices it returns the range of matrix rows associated with rows of a vector that 6929 would contain the result of a matrix vector product with this matrix. See [Matrix 6930 Layouts](sec_matlayout) for details on matrix layouts. 6931 6932 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6933 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6934 @*/ 6935 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6936 { 6937 PetscFunctionBegin; 6938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6939 PetscValidType(mat, 1); 6940 if (m) PetscAssertPointer(m, 2); 6941 if (n) PetscAssertPointer(n, 3); 6942 MatCheckPreallocated(mat, 1); 6943 if (m) *m = mat->rmap->rstart; 6944 if (n) *n = mat->rmap->rend; 6945 PetscFunctionReturn(PETSC_SUCCESS); 6946 } 6947 6948 /*@C 6949 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6950 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6951 6952 Not Collective, unless matrix has not been allocated 6953 6954 Input Parameter: 6955 . mat - the matrix 6956 6957 Output Parameter: 6958 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6959 where `size` is the number of MPI processes used by `mat` 6960 6961 Level: beginner 6962 6963 Notes: 6964 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6965 6966 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6967 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6968 6969 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6970 the local values in the matrix. 6971 6972 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6973 would contain the result of a matrix vector product with this matrix. See [Matrix 6974 Layouts](sec_matlayout) for details on matrix layouts. 6975 6976 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6977 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6978 `DMDAGetGhostCorners()`, `DM` 6979 @*/ 6980 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6981 { 6982 PetscFunctionBegin; 6983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6984 PetscValidType(mat, 1); 6985 MatCheckPreallocated(mat, 1); 6986 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6987 PetscFunctionReturn(PETSC_SUCCESS); 6988 } 6989 6990 /*@C 6991 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6992 vector one multiplies this vector by that are owned by each processor. 6993 6994 Not Collective, unless matrix has not been allocated 6995 6996 Input Parameter: 6997 . mat - the matrix 6998 6999 Output Parameter: 7000 . ranges - start of each processors portion plus one more than the total length at the end 7001 7002 Level: beginner 7003 7004 Notes: 7005 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7006 7007 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7008 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7009 7010 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7011 the local values in the matrix. 7012 7013 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7014 Layouts](sec_matlayout) for details on matrix layouts. 7015 7016 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7017 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7018 `DMDAGetGhostCorners()`, `DM` 7019 @*/ 7020 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7021 { 7022 PetscFunctionBegin; 7023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7024 PetscValidType(mat, 1); 7025 MatCheckPreallocated(mat, 1); 7026 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7027 PetscFunctionReturn(PETSC_SUCCESS); 7028 } 7029 7030 /*@ 7031 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7032 7033 Not Collective 7034 7035 Input Parameter: 7036 . A - matrix 7037 7038 Output Parameters: 7039 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7040 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7041 7042 Level: intermediate 7043 7044 Note: 7045 You should call `ISDestroy()` on the returned `IS` 7046 7047 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7048 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7049 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7050 details on matrix layouts. 7051 7052 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7053 @*/ 7054 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7055 { 7056 PetscErrorCode (*f)(Mat, IS *, IS *); 7057 7058 PetscFunctionBegin; 7059 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7060 PetscValidType(A, 1); 7061 MatCheckPreallocated(A, 1); 7062 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7063 if (f) { 7064 PetscCall((*f)(A, rows, cols)); 7065 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7066 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7067 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7068 } 7069 PetscFunctionReturn(PETSC_SUCCESS); 7070 } 7071 7072 /*@ 7073 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7074 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7075 to complete the factorization. 7076 7077 Collective 7078 7079 Input Parameters: 7080 + fact - the factorized matrix obtained with `MatGetFactor()` 7081 . mat - the matrix 7082 . row - row permutation 7083 . col - column permutation 7084 - info - structure containing 7085 .vb 7086 levels - number of levels of fill. 7087 expected fill - as ratio of original fill. 7088 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7089 missing diagonal entries) 7090 .ve 7091 7092 Level: developer 7093 7094 Notes: 7095 See [Matrix Factorization](sec_matfactor) for additional information. 7096 7097 Most users should employ the `KSP` interface for linear solvers 7098 instead of working directly with matrix algebra routines such as this. 7099 See, e.g., `KSPCreate()`. 7100 7101 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7102 7103 Developer Note: 7104 The Fortran interface is not autogenerated as the 7105 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7106 7107 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7108 `MatGetOrdering()`, `MatFactorInfo` 7109 @*/ 7110 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7111 { 7112 PetscFunctionBegin; 7113 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7114 PetscValidType(mat, 2); 7115 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7116 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7117 PetscAssertPointer(info, 5); 7118 PetscAssertPointer(fact, 1); 7119 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7120 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7121 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7122 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7123 MatCheckPreallocated(mat, 2); 7124 7125 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7126 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7127 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7128 PetscFunctionReturn(PETSC_SUCCESS); 7129 } 7130 7131 /*@ 7132 MatICCFactorSymbolic - Performs symbolic incomplete 7133 Cholesky factorization for a symmetric matrix. Use 7134 `MatCholeskyFactorNumeric()` to complete the factorization. 7135 7136 Collective 7137 7138 Input Parameters: 7139 + fact - the factorized matrix obtained with `MatGetFactor()` 7140 . mat - the matrix to be factored 7141 . perm - row and column permutation 7142 - info - structure containing 7143 .vb 7144 levels - number of levels of fill. 7145 expected fill - as ratio of original fill. 7146 .ve 7147 7148 Level: developer 7149 7150 Notes: 7151 Most users should employ the `KSP` interface for linear solvers 7152 instead of working directly with matrix algebra routines such as this. 7153 See, e.g., `KSPCreate()`. 7154 7155 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7156 7157 Developer Note: 7158 The Fortran interface is not autogenerated as the 7159 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7160 7161 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7162 @*/ 7163 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7164 { 7165 PetscFunctionBegin; 7166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7167 PetscValidType(mat, 2); 7168 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7169 PetscAssertPointer(info, 4); 7170 PetscAssertPointer(fact, 1); 7171 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7172 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7173 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7174 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7175 MatCheckPreallocated(mat, 2); 7176 7177 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7178 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7179 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7180 PetscFunctionReturn(PETSC_SUCCESS); 7181 } 7182 7183 /*@C 7184 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7185 points to an array of valid matrices, they may be reused to store the new 7186 submatrices. 7187 7188 Collective 7189 7190 Input Parameters: 7191 + mat - the matrix 7192 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7193 . irow - index set of rows to extract 7194 . icol - index set of columns to extract 7195 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7196 7197 Output Parameter: 7198 . submat - the array of submatrices 7199 7200 Level: advanced 7201 7202 Notes: 7203 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7204 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7205 to extract a parallel submatrix. 7206 7207 Some matrix types place restrictions on the row and column 7208 indices, such as that they be sorted or that they be equal to each other. 7209 7210 The index sets may not have duplicate entries. 7211 7212 When extracting submatrices from a parallel matrix, each processor can 7213 form a different submatrix by setting the rows and columns of its 7214 individual index sets according to the local submatrix desired. 7215 7216 When finished using the submatrices, the user should destroy 7217 them with `MatDestroySubMatrices()`. 7218 7219 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7220 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7221 7222 This routine creates the matrices in submat; you should NOT create them before 7223 calling it. It also allocates the array of matrix pointers submat. 7224 7225 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7226 request one row/column in a block, they must request all rows/columns that are in 7227 that block. For example, if the block size is 2 you cannot request just row 0 and 7228 column 0. 7229 7230 Fortran Note: 7231 .vb 7232 Mat, pointer :: submat(:) 7233 .ve 7234 7235 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7236 @*/ 7237 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7238 { 7239 PetscInt i; 7240 PetscBool eq; 7241 7242 PetscFunctionBegin; 7243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7244 PetscValidType(mat, 1); 7245 if (n) { 7246 PetscAssertPointer(irow, 3); 7247 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7248 PetscAssertPointer(icol, 4); 7249 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7250 } 7251 PetscAssertPointer(submat, 6); 7252 if (n && scall == MAT_REUSE_MATRIX) { 7253 PetscAssertPointer(*submat, 6); 7254 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7255 } 7256 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7257 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7258 MatCheckPreallocated(mat, 1); 7259 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7260 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7261 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7262 for (i = 0; i < n; i++) { 7263 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7264 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7265 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7266 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7267 if (mat->boundtocpu && mat->bindingpropagates) { 7268 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7269 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7270 } 7271 #endif 7272 } 7273 PetscFunctionReturn(PETSC_SUCCESS); 7274 } 7275 7276 /*@C 7277 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7278 7279 Collective 7280 7281 Input Parameters: 7282 + mat - the matrix 7283 . n - the number of submatrixes to be extracted 7284 . irow - index set of rows to extract 7285 . icol - index set of columns to extract 7286 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7287 7288 Output Parameter: 7289 . submat - the array of submatrices 7290 7291 Level: advanced 7292 7293 Note: 7294 This is used by `PCGASM` 7295 7296 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7297 @*/ 7298 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7299 { 7300 PetscInt i; 7301 PetscBool eq; 7302 7303 PetscFunctionBegin; 7304 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7305 PetscValidType(mat, 1); 7306 if (n) { 7307 PetscAssertPointer(irow, 3); 7308 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7309 PetscAssertPointer(icol, 4); 7310 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7311 } 7312 PetscAssertPointer(submat, 6); 7313 if (n && scall == MAT_REUSE_MATRIX) { 7314 PetscAssertPointer(*submat, 6); 7315 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7316 } 7317 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7318 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7319 MatCheckPreallocated(mat, 1); 7320 7321 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7322 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7323 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7324 for (i = 0; i < n; i++) { 7325 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7326 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7327 } 7328 PetscFunctionReturn(PETSC_SUCCESS); 7329 } 7330 7331 /*@C 7332 MatDestroyMatrices - Destroys an array of matrices 7333 7334 Collective 7335 7336 Input Parameters: 7337 + n - the number of local matrices 7338 - mat - the matrices (this is a pointer to the array of matrices) 7339 7340 Level: advanced 7341 7342 Notes: 7343 Frees not only the matrices, but also the array that contains the matrices 7344 7345 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7346 7347 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7348 @*/ 7349 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7350 { 7351 PetscInt i; 7352 7353 PetscFunctionBegin; 7354 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7355 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7356 PetscAssertPointer(mat, 2); 7357 7358 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7359 7360 /* memory is allocated even if n = 0 */ 7361 PetscCall(PetscFree(*mat)); 7362 PetscFunctionReturn(PETSC_SUCCESS); 7363 } 7364 7365 /*@C 7366 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7367 7368 Collective 7369 7370 Input Parameters: 7371 + n - the number of local matrices 7372 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7373 7374 Level: advanced 7375 7376 Note: 7377 Frees not only the matrices, but also the array that contains the matrices 7378 7379 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7380 @*/ 7381 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7382 { 7383 Mat mat0; 7384 7385 PetscFunctionBegin; 7386 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7387 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7388 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7389 PetscAssertPointer(mat, 2); 7390 7391 mat0 = (*mat)[0]; 7392 if (mat0 && mat0->ops->destroysubmatrices) { 7393 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7394 } else { 7395 PetscCall(MatDestroyMatrices(n, mat)); 7396 } 7397 PetscFunctionReturn(PETSC_SUCCESS); 7398 } 7399 7400 /*@ 7401 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7402 7403 Collective 7404 7405 Input Parameter: 7406 . mat - the matrix 7407 7408 Output Parameter: 7409 . matstruct - the sequential matrix with the nonzero structure of `mat` 7410 7411 Level: developer 7412 7413 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7414 @*/ 7415 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7416 { 7417 PetscFunctionBegin; 7418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7419 PetscAssertPointer(matstruct, 2); 7420 7421 PetscValidType(mat, 1); 7422 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7423 MatCheckPreallocated(mat, 1); 7424 7425 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7426 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7427 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7428 PetscFunctionReturn(PETSC_SUCCESS); 7429 } 7430 7431 /*@C 7432 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7433 7434 Collective 7435 7436 Input Parameter: 7437 . mat - the matrix 7438 7439 Level: advanced 7440 7441 Note: 7442 This is not needed, one can just call `MatDestroy()` 7443 7444 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7445 @*/ 7446 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7447 { 7448 PetscFunctionBegin; 7449 PetscAssertPointer(mat, 1); 7450 PetscCall(MatDestroy(mat)); 7451 PetscFunctionReturn(PETSC_SUCCESS); 7452 } 7453 7454 /*@ 7455 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7456 replaces the index sets by larger ones that represent submatrices with 7457 additional overlap. 7458 7459 Collective 7460 7461 Input Parameters: 7462 + mat - the matrix 7463 . n - the number of index sets 7464 . is - the array of index sets (these index sets will changed during the call) 7465 - ov - the additional overlap requested 7466 7467 Options Database Key: 7468 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7469 7470 Level: developer 7471 7472 Note: 7473 The computed overlap preserves the matrix block sizes when the blocks are square. 7474 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7475 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7476 7477 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7478 @*/ 7479 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7480 { 7481 PetscInt i, bs, cbs; 7482 7483 PetscFunctionBegin; 7484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7485 PetscValidType(mat, 1); 7486 PetscValidLogicalCollectiveInt(mat, n, 2); 7487 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7488 if (n) { 7489 PetscAssertPointer(is, 3); 7490 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7491 } 7492 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7493 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7494 MatCheckPreallocated(mat, 1); 7495 7496 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7497 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7498 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7499 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7500 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7501 if (bs == cbs) { 7502 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7503 } 7504 PetscFunctionReturn(PETSC_SUCCESS); 7505 } 7506 7507 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7508 7509 /*@ 7510 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7511 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7512 additional overlap. 7513 7514 Collective 7515 7516 Input Parameters: 7517 + mat - the matrix 7518 . n - the number of index sets 7519 . is - the array of index sets (these index sets will changed during the call) 7520 - ov - the additional overlap requested 7521 7522 ` Options Database Key: 7523 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7524 7525 Level: developer 7526 7527 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7528 @*/ 7529 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7530 { 7531 PetscInt i; 7532 7533 PetscFunctionBegin; 7534 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7535 PetscValidType(mat, 1); 7536 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7537 if (n) { 7538 PetscAssertPointer(is, 3); 7539 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7540 } 7541 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7542 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7543 MatCheckPreallocated(mat, 1); 7544 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7545 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7546 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7547 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7548 PetscFunctionReturn(PETSC_SUCCESS); 7549 } 7550 7551 /*@ 7552 MatGetBlockSize - Returns the matrix block size. 7553 7554 Not Collective 7555 7556 Input Parameter: 7557 . mat - the matrix 7558 7559 Output Parameter: 7560 . bs - block size 7561 7562 Level: intermediate 7563 7564 Notes: 7565 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7566 7567 If the block size has not been set yet this routine returns 1. 7568 7569 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7570 @*/ 7571 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7572 { 7573 PetscFunctionBegin; 7574 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7575 PetscAssertPointer(bs, 2); 7576 *bs = mat->rmap->bs; 7577 PetscFunctionReturn(PETSC_SUCCESS); 7578 } 7579 7580 /*@ 7581 MatGetBlockSizes - Returns the matrix block row and column sizes. 7582 7583 Not Collective 7584 7585 Input Parameter: 7586 . mat - the matrix 7587 7588 Output Parameters: 7589 + rbs - row block size 7590 - cbs - column block size 7591 7592 Level: intermediate 7593 7594 Notes: 7595 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7596 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7597 7598 If a block size has not been set yet this routine returns 1. 7599 7600 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7601 @*/ 7602 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7603 { 7604 PetscFunctionBegin; 7605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7606 if (rbs) PetscAssertPointer(rbs, 2); 7607 if (cbs) PetscAssertPointer(cbs, 3); 7608 if (rbs) *rbs = mat->rmap->bs; 7609 if (cbs) *cbs = mat->cmap->bs; 7610 PetscFunctionReturn(PETSC_SUCCESS); 7611 } 7612 7613 /*@ 7614 MatSetBlockSize - Sets the matrix block size. 7615 7616 Logically Collective 7617 7618 Input Parameters: 7619 + mat - the matrix 7620 - bs - block size 7621 7622 Level: intermediate 7623 7624 Notes: 7625 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7626 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7627 7628 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7629 is compatible with the matrix local sizes. 7630 7631 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7632 @*/ 7633 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7634 { 7635 PetscFunctionBegin; 7636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7637 PetscValidLogicalCollectiveInt(mat, bs, 2); 7638 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7639 PetscFunctionReturn(PETSC_SUCCESS); 7640 } 7641 7642 typedef struct { 7643 PetscInt n; 7644 IS *is; 7645 Mat *mat; 7646 PetscObjectState nonzerostate; 7647 Mat C; 7648 } EnvelopeData; 7649 7650 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7651 { 7652 EnvelopeData *edata = (EnvelopeData *)*ptr; 7653 7654 PetscFunctionBegin; 7655 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7656 PetscCall(PetscFree(edata->is)); 7657 PetscCall(PetscFree(edata)); 7658 PetscFunctionReturn(PETSC_SUCCESS); 7659 } 7660 7661 /*@ 7662 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7663 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7664 7665 Collective 7666 7667 Input Parameter: 7668 . mat - the matrix 7669 7670 Level: intermediate 7671 7672 Notes: 7673 There can be zeros within the blocks 7674 7675 The blocks can overlap between processes, including laying on more than two processes 7676 7677 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7678 @*/ 7679 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7680 { 7681 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7682 PetscInt *diag, *odiag, sc; 7683 VecScatter scatter; 7684 PetscScalar *seqv; 7685 const PetscScalar *parv; 7686 const PetscInt *ia, *ja; 7687 PetscBool set, flag, done; 7688 Mat AA = mat, A; 7689 MPI_Comm comm; 7690 PetscMPIInt rank, size, tag; 7691 MPI_Status status; 7692 PetscContainer container; 7693 EnvelopeData *edata; 7694 Vec seq, par; 7695 IS isglobal; 7696 7697 PetscFunctionBegin; 7698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7699 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7700 if (!set || !flag) { 7701 /* TODO: only needs nonzero structure of transpose */ 7702 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7703 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7704 } 7705 PetscCall(MatAIJGetLocalMat(AA, &A)); 7706 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7707 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7708 7709 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7710 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7711 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7712 PetscCallMPI(MPI_Comm_size(comm, &size)); 7713 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7714 7715 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7716 7717 if (rank > 0) { 7718 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7719 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7720 } 7721 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7722 for (i = 0; i < n; i++) { 7723 env = PetscMax(env, ja[ia[i + 1] - 1]); 7724 II = rstart + i; 7725 if (env == II) { 7726 starts[lblocks] = tbs; 7727 sizes[lblocks++] = 1 + II - tbs; 7728 tbs = 1 + II; 7729 } 7730 } 7731 if (rank < size - 1) { 7732 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7733 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7734 } 7735 7736 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7737 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7738 PetscCall(MatDestroy(&A)); 7739 7740 PetscCall(PetscNew(&edata)); 7741 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7742 edata->n = lblocks; 7743 /* create IS needed for extracting blocks from the original matrix */ 7744 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7745 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7746 7747 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7748 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7749 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7750 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7751 PetscCall(MatSetType(edata->C, MATAIJ)); 7752 7753 /* Communicate the start and end of each row, from each block to the correct rank */ 7754 /* TODO: Use PetscSF instead of VecScatter */ 7755 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7756 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7757 PetscCall(VecGetArrayWrite(seq, &seqv)); 7758 for (PetscInt i = 0; i < lblocks; i++) { 7759 for (PetscInt j = 0; j < sizes[i]; j++) { 7760 seqv[cnt] = starts[i]; 7761 seqv[cnt + 1] = starts[i] + sizes[i]; 7762 cnt += 2; 7763 } 7764 } 7765 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7766 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7767 sc -= cnt; 7768 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7769 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7770 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7771 PetscCall(ISDestroy(&isglobal)); 7772 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7773 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7774 PetscCall(VecScatterDestroy(&scatter)); 7775 PetscCall(VecDestroy(&seq)); 7776 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7777 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7778 PetscCall(VecGetArrayRead(par, &parv)); 7779 cnt = 0; 7780 PetscCall(MatGetSize(mat, NULL, &n)); 7781 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7782 PetscInt start, end, d = 0, od = 0; 7783 7784 start = (PetscInt)PetscRealPart(parv[cnt]); 7785 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7786 cnt += 2; 7787 7788 if (start < cstart) { 7789 od += cstart - start + n - cend; 7790 d += cend - cstart; 7791 } else if (start < cend) { 7792 od += n - cend; 7793 d += cend - start; 7794 } else od += n - start; 7795 if (end <= cstart) { 7796 od -= cstart - end + n - cend; 7797 d -= cend - cstart; 7798 } else if (end < cend) { 7799 od -= n - cend; 7800 d -= cend - end; 7801 } else od -= n - end; 7802 7803 odiag[i] = od; 7804 diag[i] = d; 7805 } 7806 PetscCall(VecRestoreArrayRead(par, &parv)); 7807 PetscCall(VecDestroy(&par)); 7808 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7809 PetscCall(PetscFree2(diag, odiag)); 7810 PetscCall(PetscFree2(sizes, starts)); 7811 7812 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7813 PetscCall(PetscContainerSetPointer(container, edata)); 7814 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7815 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7816 PetscCall(PetscObjectDereference((PetscObject)container)); 7817 PetscFunctionReturn(PETSC_SUCCESS); 7818 } 7819 7820 /*@ 7821 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7822 7823 Collective 7824 7825 Input Parameters: 7826 + A - the matrix 7827 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7828 7829 Output Parameter: 7830 . C - matrix with inverted block diagonal of `A` 7831 7832 Level: advanced 7833 7834 Note: 7835 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7836 7837 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7838 @*/ 7839 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7840 { 7841 PetscContainer container; 7842 EnvelopeData *edata; 7843 PetscObjectState nonzerostate; 7844 7845 PetscFunctionBegin; 7846 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7847 if (!container) { 7848 PetscCall(MatComputeVariableBlockEnvelope(A)); 7849 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7850 } 7851 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7852 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7853 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7854 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7855 7856 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7857 *C = edata->C; 7858 7859 for (PetscInt i = 0; i < edata->n; i++) { 7860 Mat D; 7861 PetscScalar *dvalues; 7862 7863 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7864 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7865 PetscCall(MatSeqDenseInvert(D)); 7866 PetscCall(MatDenseGetArray(D, &dvalues)); 7867 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7868 PetscCall(MatDestroy(&D)); 7869 } 7870 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7871 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7872 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7873 PetscFunctionReturn(PETSC_SUCCESS); 7874 } 7875 7876 /*@ 7877 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7878 7879 Not Collective 7880 7881 Input Parameters: 7882 + mat - the matrix 7883 . nblocks - the number of blocks on this process, each block can only exist on a single process 7884 - bsizes - the block sizes 7885 7886 Level: intermediate 7887 7888 Notes: 7889 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7890 7891 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. 7892 7893 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7894 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7895 @*/ 7896 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7897 { 7898 PetscInt ncnt = 0, nlocal; 7899 7900 PetscFunctionBegin; 7901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7902 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7903 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); 7904 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7905 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); 7906 PetscCall(PetscFree(mat->bsizes)); 7907 mat->nblocks = nblocks; 7908 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7909 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7910 PetscFunctionReturn(PETSC_SUCCESS); 7911 } 7912 7913 /*@C 7914 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7915 7916 Not Collective; No Fortran Support 7917 7918 Input Parameter: 7919 . mat - the matrix 7920 7921 Output Parameters: 7922 + nblocks - the number of blocks on this process 7923 - bsizes - the block sizes 7924 7925 Level: intermediate 7926 7927 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7928 @*/ 7929 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7930 { 7931 PetscFunctionBegin; 7932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7933 if (nblocks) *nblocks = mat->nblocks; 7934 if (bsizes) *bsizes = mat->bsizes; 7935 PetscFunctionReturn(PETSC_SUCCESS); 7936 } 7937 7938 /*@ 7939 MatSetBlockSizes - Sets the matrix block row and column sizes. 7940 7941 Logically Collective 7942 7943 Input Parameters: 7944 + mat - the matrix 7945 . rbs - row block size 7946 - cbs - column block size 7947 7948 Level: intermediate 7949 7950 Notes: 7951 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7952 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7953 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7954 7955 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7956 are compatible with the matrix local sizes. 7957 7958 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7959 7960 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7961 @*/ 7962 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7963 { 7964 PetscFunctionBegin; 7965 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7966 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7967 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7968 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7969 if (mat->rmap->refcnt) { 7970 ISLocalToGlobalMapping l2g = NULL; 7971 PetscLayout nmap = NULL; 7972 7973 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7974 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7975 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7976 mat->rmap = nmap; 7977 mat->rmap->mapping = l2g; 7978 } 7979 if (mat->cmap->refcnt) { 7980 ISLocalToGlobalMapping l2g = NULL; 7981 PetscLayout nmap = NULL; 7982 7983 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7984 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7985 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7986 mat->cmap = nmap; 7987 mat->cmap->mapping = l2g; 7988 } 7989 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7990 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7991 PetscFunctionReturn(PETSC_SUCCESS); 7992 } 7993 7994 /*@ 7995 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7996 7997 Logically Collective 7998 7999 Input Parameters: 8000 + mat - the matrix 8001 . fromRow - matrix from which to copy row block size 8002 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8003 8004 Level: developer 8005 8006 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8007 @*/ 8008 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8009 { 8010 PetscFunctionBegin; 8011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8012 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8013 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8014 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8015 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8016 PetscFunctionReturn(PETSC_SUCCESS); 8017 } 8018 8019 /*@ 8020 MatResidual - Default routine to calculate the residual r = b - Ax 8021 8022 Collective 8023 8024 Input Parameters: 8025 + mat - the matrix 8026 . b - the right-hand-side 8027 - x - the approximate solution 8028 8029 Output Parameter: 8030 . r - location to store the residual 8031 8032 Level: developer 8033 8034 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8035 @*/ 8036 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8037 { 8038 PetscFunctionBegin; 8039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8040 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8041 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8042 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8043 PetscValidType(mat, 1); 8044 MatCheckPreallocated(mat, 1); 8045 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8046 if (!mat->ops->residual) { 8047 PetscCall(MatMult(mat, x, r)); 8048 PetscCall(VecAYPX(r, -1.0, b)); 8049 } else { 8050 PetscUseTypeMethod(mat, residual, b, x, r); 8051 } 8052 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8053 PetscFunctionReturn(PETSC_SUCCESS); 8054 } 8055 8056 /*@C 8057 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8058 8059 Collective 8060 8061 Input Parameters: 8062 + mat - the matrix 8063 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8064 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8065 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8066 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8067 always used. 8068 8069 Output Parameters: 8070 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8071 . 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 8072 . ja - the column indices, use `NULL` if not needed 8073 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8074 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8075 8076 Level: developer 8077 8078 Notes: 8079 You CANNOT change any of the ia[] or ja[] values. 8080 8081 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8082 8083 Fortran Notes: 8084 Use 8085 .vb 8086 PetscInt, pointer :: ia(:),ja(:) 8087 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8088 ! Access the ith and jth entries via ia(i) and ja(j) 8089 .ve 8090 8091 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8092 @*/ 8093 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8094 { 8095 PetscFunctionBegin; 8096 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8097 PetscValidType(mat, 1); 8098 if (n) PetscAssertPointer(n, 5); 8099 if (ia) PetscAssertPointer(ia, 6); 8100 if (ja) PetscAssertPointer(ja, 7); 8101 if (done) PetscAssertPointer(done, 8); 8102 MatCheckPreallocated(mat, 1); 8103 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8104 else { 8105 if (done) *done = PETSC_TRUE; 8106 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8107 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8108 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8109 } 8110 PetscFunctionReturn(PETSC_SUCCESS); 8111 } 8112 8113 /*@C 8114 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8115 8116 Collective 8117 8118 Input Parameters: 8119 + mat - the matrix 8120 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8121 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8122 symmetrized 8123 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8124 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8125 always used. 8126 . n - number of columns in the (possibly compressed) matrix 8127 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8128 - ja - the row indices 8129 8130 Output Parameter: 8131 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8132 8133 Level: developer 8134 8135 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8136 @*/ 8137 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8138 { 8139 PetscFunctionBegin; 8140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8141 PetscValidType(mat, 1); 8142 PetscAssertPointer(n, 5); 8143 if (ia) PetscAssertPointer(ia, 6); 8144 if (ja) PetscAssertPointer(ja, 7); 8145 PetscAssertPointer(done, 8); 8146 MatCheckPreallocated(mat, 1); 8147 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8148 else { 8149 *done = PETSC_TRUE; 8150 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8151 } 8152 PetscFunctionReturn(PETSC_SUCCESS); 8153 } 8154 8155 /*@C 8156 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8157 8158 Collective 8159 8160 Input Parameters: 8161 + mat - the matrix 8162 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8163 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8164 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8165 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8166 always used. 8167 . n - size of (possibly compressed) matrix 8168 . ia - the row pointers 8169 - ja - the column indices 8170 8171 Output Parameter: 8172 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8173 8174 Level: developer 8175 8176 Note: 8177 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8178 us of the array after it has been restored. If you pass `NULL`, it will 8179 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8180 8181 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8182 @*/ 8183 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8184 { 8185 PetscFunctionBegin; 8186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8187 PetscValidType(mat, 1); 8188 if (ia) PetscAssertPointer(ia, 6); 8189 if (ja) PetscAssertPointer(ja, 7); 8190 if (done) PetscAssertPointer(done, 8); 8191 MatCheckPreallocated(mat, 1); 8192 8193 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8194 else { 8195 if (done) *done = PETSC_TRUE; 8196 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8197 if (n) *n = 0; 8198 if (ia) *ia = NULL; 8199 if (ja) *ja = NULL; 8200 } 8201 PetscFunctionReturn(PETSC_SUCCESS); 8202 } 8203 8204 /*@C 8205 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8206 8207 Collective 8208 8209 Input Parameters: 8210 + mat - the matrix 8211 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8212 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8213 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8214 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8215 always used. 8216 8217 Output Parameters: 8218 + n - size of (possibly compressed) matrix 8219 . ia - the column pointers 8220 . ja - the row indices 8221 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8222 8223 Level: developer 8224 8225 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8226 @*/ 8227 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8228 { 8229 PetscFunctionBegin; 8230 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8231 PetscValidType(mat, 1); 8232 if (ia) PetscAssertPointer(ia, 6); 8233 if (ja) PetscAssertPointer(ja, 7); 8234 PetscAssertPointer(done, 8); 8235 MatCheckPreallocated(mat, 1); 8236 8237 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8238 else { 8239 *done = PETSC_TRUE; 8240 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8241 if (n) *n = 0; 8242 if (ia) *ia = NULL; 8243 if (ja) *ja = NULL; 8244 } 8245 PetscFunctionReturn(PETSC_SUCCESS); 8246 } 8247 8248 /*@ 8249 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8250 `MatGetColumnIJ()`. 8251 8252 Collective 8253 8254 Input Parameters: 8255 + mat - the matrix 8256 . ncolors - maximum color value 8257 . n - number of entries in colorarray 8258 - colorarray - array indicating color for each column 8259 8260 Output Parameter: 8261 . iscoloring - coloring generated using colorarray information 8262 8263 Level: developer 8264 8265 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8266 @*/ 8267 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8268 { 8269 PetscFunctionBegin; 8270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8271 PetscValidType(mat, 1); 8272 PetscAssertPointer(colorarray, 4); 8273 PetscAssertPointer(iscoloring, 5); 8274 MatCheckPreallocated(mat, 1); 8275 8276 if (!mat->ops->coloringpatch) { 8277 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8278 } else { 8279 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8280 } 8281 PetscFunctionReturn(PETSC_SUCCESS); 8282 } 8283 8284 /*@ 8285 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8286 8287 Logically Collective 8288 8289 Input Parameter: 8290 . mat - the factored matrix to be reset 8291 8292 Level: developer 8293 8294 Notes: 8295 This routine should be used only with factored matrices formed by in-place 8296 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8297 format). This option can save memory, for example, when solving nonlinear 8298 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8299 ILU(0) preconditioner. 8300 8301 One can specify in-place ILU(0) factorization by calling 8302 .vb 8303 PCType(pc,PCILU); 8304 PCFactorSeUseInPlace(pc); 8305 .ve 8306 or by using the options -pc_type ilu -pc_factor_in_place 8307 8308 In-place factorization ILU(0) can also be used as a local 8309 solver for the blocks within the block Jacobi or additive Schwarz 8310 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8311 for details on setting local solver options. 8312 8313 Most users should employ the `KSP` interface for linear solvers 8314 instead of working directly with matrix algebra routines such as this. 8315 See, e.g., `KSPCreate()`. 8316 8317 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8318 @*/ 8319 PetscErrorCode MatSetUnfactored(Mat mat) 8320 { 8321 PetscFunctionBegin; 8322 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8323 PetscValidType(mat, 1); 8324 MatCheckPreallocated(mat, 1); 8325 mat->factortype = MAT_FACTOR_NONE; 8326 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8327 PetscUseTypeMethod(mat, setunfactored); 8328 PetscFunctionReturn(PETSC_SUCCESS); 8329 } 8330 8331 /*@ 8332 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8333 as the original matrix. 8334 8335 Collective 8336 8337 Input Parameters: 8338 + mat - the original matrix 8339 . isrow - parallel `IS` containing the rows this processor should obtain 8340 . 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. 8341 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8342 8343 Output Parameter: 8344 . newmat - the new submatrix, of the same type as the original matrix 8345 8346 Level: advanced 8347 8348 Notes: 8349 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8350 8351 Some matrix types place restrictions on the row and column indices, such 8352 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; 8353 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8354 8355 The index sets may not have duplicate entries. 8356 8357 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8358 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8359 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8360 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8361 you are finished using it. 8362 8363 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8364 the input matrix. 8365 8366 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8367 8368 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8369 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8370 8371 Example usage: 8372 Consider the following 8x8 matrix with 34 non-zero values, that is 8373 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8374 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8375 as follows 8376 .vb 8377 1 2 0 | 0 3 0 | 0 4 8378 Proc0 0 5 6 | 7 0 0 | 8 0 8379 9 0 10 | 11 0 0 | 12 0 8380 ------------------------------------- 8381 13 0 14 | 15 16 17 | 0 0 8382 Proc1 0 18 0 | 19 20 21 | 0 0 8383 0 0 0 | 22 23 0 | 24 0 8384 ------------------------------------- 8385 Proc2 25 26 27 | 0 0 28 | 29 0 8386 30 0 0 | 31 32 33 | 0 34 8387 .ve 8388 8389 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8390 8391 .vb 8392 2 0 | 0 3 0 | 0 8393 Proc0 5 6 | 7 0 0 | 8 8394 ------------------------------- 8395 Proc1 18 0 | 19 20 21 | 0 8396 ------------------------------- 8397 Proc2 26 27 | 0 0 28 | 29 8398 0 0 | 31 32 33 | 0 8399 .ve 8400 8401 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8402 @*/ 8403 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8404 { 8405 PetscMPIInt size; 8406 Mat *local; 8407 IS iscoltmp; 8408 PetscBool flg; 8409 8410 PetscFunctionBegin; 8411 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8412 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8413 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8414 PetscAssertPointer(newmat, 5); 8415 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8416 PetscValidType(mat, 1); 8417 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8418 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8419 8420 MatCheckPreallocated(mat, 1); 8421 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8422 8423 if (!iscol || isrow == iscol) { 8424 PetscBool stride; 8425 PetscMPIInt grabentirematrix = 0, grab; 8426 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8427 if (stride) { 8428 PetscInt first, step, n, rstart, rend; 8429 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8430 if (step == 1) { 8431 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8432 if (rstart == first) { 8433 PetscCall(ISGetLocalSize(isrow, &n)); 8434 if (n == rend - rstart) grabentirematrix = 1; 8435 } 8436 } 8437 } 8438 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8439 if (grab) { 8440 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8441 if (cll == MAT_INITIAL_MATRIX) { 8442 *newmat = mat; 8443 PetscCall(PetscObjectReference((PetscObject)mat)); 8444 } 8445 PetscFunctionReturn(PETSC_SUCCESS); 8446 } 8447 } 8448 8449 if (!iscol) { 8450 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8451 } else { 8452 iscoltmp = iscol; 8453 } 8454 8455 /* if original matrix is on just one processor then use submatrix generated */ 8456 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8457 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8458 goto setproperties; 8459 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8460 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8461 *newmat = *local; 8462 PetscCall(PetscFree(local)); 8463 goto setproperties; 8464 } else if (!mat->ops->createsubmatrix) { 8465 /* Create a new matrix type that implements the operation using the full matrix */ 8466 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8467 switch (cll) { 8468 case MAT_INITIAL_MATRIX: 8469 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8470 break; 8471 case MAT_REUSE_MATRIX: 8472 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8473 break; 8474 default: 8475 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8476 } 8477 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8478 goto setproperties; 8479 } 8480 8481 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8482 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8483 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8484 8485 setproperties: 8486 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8487 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8488 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8489 } 8490 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8491 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8492 PetscFunctionReturn(PETSC_SUCCESS); 8493 } 8494 8495 /*@ 8496 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8497 8498 Not Collective 8499 8500 Input Parameters: 8501 + A - the matrix we wish to propagate options from 8502 - B - the matrix we wish to propagate options to 8503 8504 Level: beginner 8505 8506 Note: 8507 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8508 8509 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8510 @*/ 8511 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8512 { 8513 PetscFunctionBegin; 8514 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8515 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8516 B->symmetry_eternal = A->symmetry_eternal; 8517 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8518 B->symmetric = A->symmetric; 8519 B->structurally_symmetric = A->structurally_symmetric; 8520 B->spd = A->spd; 8521 B->hermitian = A->hermitian; 8522 PetscFunctionReturn(PETSC_SUCCESS); 8523 } 8524 8525 /*@ 8526 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8527 used during the assembly process to store values that belong to 8528 other processors. 8529 8530 Not Collective 8531 8532 Input Parameters: 8533 + mat - the matrix 8534 . size - the initial size of the stash. 8535 - bsize - the initial size of the block-stash(if used). 8536 8537 Options Database Keys: 8538 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8539 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8540 8541 Level: intermediate 8542 8543 Notes: 8544 The block-stash is used for values set with `MatSetValuesBlocked()` while 8545 the stash is used for values set with `MatSetValues()` 8546 8547 Run with the option -info and look for output of the form 8548 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8549 to determine the appropriate value, MM, to use for size and 8550 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8551 to determine the value, BMM to use for bsize 8552 8553 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8554 @*/ 8555 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8556 { 8557 PetscFunctionBegin; 8558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8559 PetscValidType(mat, 1); 8560 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8561 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8562 PetscFunctionReturn(PETSC_SUCCESS); 8563 } 8564 8565 /*@ 8566 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8567 the matrix 8568 8569 Neighbor-wise Collective 8570 8571 Input Parameters: 8572 + A - the matrix 8573 . x - the vector to be multiplied by the interpolation operator 8574 - y - the vector to be added to the result 8575 8576 Output Parameter: 8577 . w - the resulting vector 8578 8579 Level: intermediate 8580 8581 Notes: 8582 `w` may be the same vector as `y`. 8583 8584 This allows one to use either the restriction or interpolation (its transpose) 8585 matrix to do the interpolation 8586 8587 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8588 @*/ 8589 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8590 { 8591 PetscInt M, N, Ny; 8592 8593 PetscFunctionBegin; 8594 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8595 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8596 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8597 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8598 PetscCall(MatGetSize(A, &M, &N)); 8599 PetscCall(VecGetSize(y, &Ny)); 8600 if (M == Ny) { 8601 PetscCall(MatMultAdd(A, x, y, w)); 8602 } else { 8603 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8604 } 8605 PetscFunctionReturn(PETSC_SUCCESS); 8606 } 8607 8608 /*@ 8609 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8610 the matrix 8611 8612 Neighbor-wise Collective 8613 8614 Input Parameters: 8615 + A - the matrix 8616 - x - the vector to be interpolated 8617 8618 Output Parameter: 8619 . y - the resulting vector 8620 8621 Level: intermediate 8622 8623 Note: 8624 This allows one to use either the restriction or interpolation (its transpose) 8625 matrix to do the interpolation 8626 8627 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8628 @*/ 8629 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8630 { 8631 PetscInt M, N, Ny; 8632 8633 PetscFunctionBegin; 8634 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8635 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8636 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8637 PetscCall(MatGetSize(A, &M, &N)); 8638 PetscCall(VecGetSize(y, &Ny)); 8639 if (M == Ny) { 8640 PetscCall(MatMult(A, x, y)); 8641 } else { 8642 PetscCall(MatMultTranspose(A, x, y)); 8643 } 8644 PetscFunctionReturn(PETSC_SUCCESS); 8645 } 8646 8647 /*@ 8648 MatRestrict - $y = A*x$ or $A^T*x$ 8649 8650 Neighbor-wise Collective 8651 8652 Input Parameters: 8653 + A - the matrix 8654 - x - the vector to be restricted 8655 8656 Output Parameter: 8657 . y - the resulting vector 8658 8659 Level: intermediate 8660 8661 Note: 8662 This allows one to use either the restriction or interpolation (its transpose) 8663 matrix to do the restriction 8664 8665 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8666 @*/ 8667 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8668 { 8669 PetscInt M, N, Nx; 8670 8671 PetscFunctionBegin; 8672 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8673 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8674 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8675 PetscCall(MatGetSize(A, &M, &N)); 8676 PetscCall(VecGetSize(x, &Nx)); 8677 if (M == Nx) { 8678 PetscCall(MatMultTranspose(A, x, y)); 8679 } else { 8680 PetscCall(MatMult(A, x, y)); 8681 } 8682 PetscFunctionReturn(PETSC_SUCCESS); 8683 } 8684 8685 /*@ 8686 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8687 8688 Neighbor-wise Collective 8689 8690 Input Parameters: 8691 + A - the matrix 8692 . x - the input dense matrix to be multiplied 8693 - w - the input dense matrix to be added to the result 8694 8695 Output Parameter: 8696 . y - the output dense matrix 8697 8698 Level: intermediate 8699 8700 Note: 8701 This allows one to use either the restriction or interpolation (its transpose) 8702 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8703 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8704 8705 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8706 @*/ 8707 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8708 { 8709 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8710 PetscBool trans = PETSC_TRUE; 8711 MatReuse reuse = MAT_INITIAL_MATRIX; 8712 8713 PetscFunctionBegin; 8714 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8715 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8716 PetscValidType(x, 2); 8717 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8718 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8719 PetscCall(MatGetSize(A, &M, &N)); 8720 PetscCall(MatGetSize(x, &Mx, &Nx)); 8721 if (N == Mx) trans = PETSC_FALSE; 8722 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); 8723 Mo = trans ? N : M; 8724 if (*y) { 8725 PetscCall(MatGetSize(*y, &My, &Ny)); 8726 if (Mo == My && Nx == Ny) { 8727 reuse = MAT_REUSE_MATRIX; 8728 } else { 8729 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); 8730 PetscCall(MatDestroy(y)); 8731 } 8732 } 8733 8734 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8735 PetscBool flg; 8736 8737 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8738 if (w) { 8739 PetscInt My, Ny, Mw, Nw; 8740 8741 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8742 PetscCall(MatGetSize(*y, &My, &Ny)); 8743 PetscCall(MatGetSize(w, &Mw, &Nw)); 8744 if (!flg || My != Mw || Ny != Nw) w = NULL; 8745 } 8746 if (!w) { 8747 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8748 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8749 PetscCall(PetscObjectDereference((PetscObject)w)); 8750 } else { 8751 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8752 } 8753 } 8754 if (!trans) { 8755 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8756 } else { 8757 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8758 } 8759 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8760 PetscFunctionReturn(PETSC_SUCCESS); 8761 } 8762 8763 /*@ 8764 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8765 8766 Neighbor-wise Collective 8767 8768 Input Parameters: 8769 + A - the matrix 8770 - x - the input dense matrix 8771 8772 Output Parameter: 8773 . y - the output dense matrix 8774 8775 Level: intermediate 8776 8777 Note: 8778 This allows one to use either the restriction or interpolation (its transpose) 8779 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8780 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8781 8782 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8783 @*/ 8784 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8785 { 8786 PetscFunctionBegin; 8787 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8788 PetscFunctionReturn(PETSC_SUCCESS); 8789 } 8790 8791 /*@ 8792 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8793 8794 Neighbor-wise Collective 8795 8796 Input Parameters: 8797 + A - the matrix 8798 - x - the input dense matrix 8799 8800 Output Parameter: 8801 . y - the output dense matrix 8802 8803 Level: intermediate 8804 8805 Note: 8806 This allows one to use either the restriction or interpolation (its transpose) 8807 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8808 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8809 8810 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8811 @*/ 8812 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8813 { 8814 PetscFunctionBegin; 8815 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8816 PetscFunctionReturn(PETSC_SUCCESS); 8817 } 8818 8819 /*@ 8820 MatGetNullSpace - retrieves the null space of a matrix. 8821 8822 Logically Collective 8823 8824 Input Parameters: 8825 + mat - the matrix 8826 - nullsp - the null space object 8827 8828 Level: developer 8829 8830 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8831 @*/ 8832 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8833 { 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8836 PetscAssertPointer(nullsp, 2); 8837 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8838 PetscFunctionReturn(PETSC_SUCCESS); 8839 } 8840 8841 /*@C 8842 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8843 8844 Logically Collective 8845 8846 Input Parameters: 8847 + n - the number of matrices 8848 - mat - the array of matrices 8849 8850 Output Parameters: 8851 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8852 8853 Level: developer 8854 8855 Note: 8856 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8857 8858 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8859 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8860 @*/ 8861 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8862 { 8863 PetscFunctionBegin; 8864 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8865 PetscAssertPointer(mat, 2); 8866 PetscAssertPointer(nullsp, 3); 8867 8868 PetscCall(PetscCalloc1(3 * n, nullsp)); 8869 for (PetscInt i = 0; i < n; i++) { 8870 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8871 (*nullsp)[i] = mat[i]->nullsp; 8872 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8873 (*nullsp)[n + i] = mat[i]->nearnullsp; 8874 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8875 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8876 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8877 } 8878 PetscFunctionReturn(PETSC_SUCCESS); 8879 } 8880 8881 /*@C 8882 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8883 8884 Logically Collective 8885 8886 Input Parameters: 8887 + n - the number of matrices 8888 . mat - the array of matrices 8889 - nullsp - an array of null spaces 8890 8891 Level: developer 8892 8893 Note: 8894 Call `MatGetNullSpaces()` to create `nullsp` 8895 8896 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8897 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8898 @*/ 8899 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8900 { 8901 PetscFunctionBegin; 8902 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8903 PetscAssertPointer(mat, 2); 8904 PetscAssertPointer(nullsp, 3); 8905 PetscAssertPointer(*nullsp, 3); 8906 8907 for (PetscInt i = 0; i < n; i++) { 8908 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8909 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8910 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8911 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8912 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8913 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8914 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8915 } 8916 PetscCall(PetscFree(*nullsp)); 8917 PetscFunctionReturn(PETSC_SUCCESS); 8918 } 8919 8920 /*@ 8921 MatSetNullSpace - attaches a null space to a matrix. 8922 8923 Logically Collective 8924 8925 Input Parameters: 8926 + mat - the matrix 8927 - nullsp - the null space object 8928 8929 Level: advanced 8930 8931 Notes: 8932 This null space is used by the `KSP` linear solvers to solve singular systems. 8933 8934 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` 8935 8936 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 8937 to zero but the linear system will still be solved in a least squares sense. 8938 8939 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8940 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)$. 8941 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 8942 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 8943 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$). 8944 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8945 8946 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8947 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8948 routine also automatically calls `MatSetTransposeNullSpace()`. 8949 8950 The user should call `MatNullSpaceDestroy()`. 8951 8952 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8953 `KSPSetPCSide()` 8954 @*/ 8955 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8956 { 8957 PetscFunctionBegin; 8958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8959 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8960 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8961 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8962 mat->nullsp = nullsp; 8963 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8964 PetscFunctionReturn(PETSC_SUCCESS); 8965 } 8966 8967 /*@ 8968 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8969 8970 Logically Collective 8971 8972 Input Parameters: 8973 + mat - the matrix 8974 - nullsp - the null space object 8975 8976 Level: developer 8977 8978 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8979 @*/ 8980 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8981 { 8982 PetscFunctionBegin; 8983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8984 PetscValidType(mat, 1); 8985 PetscAssertPointer(nullsp, 2); 8986 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8987 PetscFunctionReturn(PETSC_SUCCESS); 8988 } 8989 8990 /*@ 8991 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8992 8993 Logically Collective 8994 8995 Input Parameters: 8996 + mat - the matrix 8997 - nullsp - the null space object 8998 8999 Level: advanced 9000 9001 Notes: 9002 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9003 9004 See `MatSetNullSpace()` 9005 9006 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9007 @*/ 9008 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9009 { 9010 PetscFunctionBegin; 9011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9012 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9013 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9014 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9015 mat->transnullsp = nullsp; 9016 PetscFunctionReturn(PETSC_SUCCESS); 9017 } 9018 9019 /*@ 9020 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9021 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9022 9023 Logically Collective 9024 9025 Input Parameters: 9026 + mat - the matrix 9027 - nullsp - the null space object 9028 9029 Level: advanced 9030 9031 Notes: 9032 Overwrites any previous near null space that may have been attached 9033 9034 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9035 9036 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9037 @*/ 9038 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9039 { 9040 PetscFunctionBegin; 9041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9042 PetscValidType(mat, 1); 9043 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9044 MatCheckPreallocated(mat, 1); 9045 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9046 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9047 mat->nearnullsp = nullsp; 9048 PetscFunctionReturn(PETSC_SUCCESS); 9049 } 9050 9051 /*@ 9052 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9053 9054 Not Collective 9055 9056 Input Parameter: 9057 . mat - the matrix 9058 9059 Output Parameter: 9060 . nullsp - the null space object, `NULL` if not set 9061 9062 Level: advanced 9063 9064 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9065 @*/ 9066 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9067 { 9068 PetscFunctionBegin; 9069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9070 PetscValidType(mat, 1); 9071 PetscAssertPointer(nullsp, 2); 9072 MatCheckPreallocated(mat, 1); 9073 *nullsp = mat->nearnullsp; 9074 PetscFunctionReturn(PETSC_SUCCESS); 9075 } 9076 9077 /*@ 9078 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9079 9080 Collective 9081 9082 Input Parameters: 9083 + mat - the matrix 9084 . row - row/column permutation 9085 - info - information on desired factorization process 9086 9087 Level: developer 9088 9089 Notes: 9090 Probably really in-place only when level of fill is zero, otherwise allocates 9091 new space to store factored matrix and deletes previous memory. 9092 9093 Most users should employ the `KSP` interface for linear solvers 9094 instead of working directly with matrix algebra routines such as this. 9095 See, e.g., `KSPCreate()`. 9096 9097 Developer Note: 9098 The Fortran interface is not autogenerated as the 9099 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9100 9101 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9102 @*/ 9103 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9104 { 9105 PetscFunctionBegin; 9106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9107 PetscValidType(mat, 1); 9108 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9109 PetscAssertPointer(info, 3); 9110 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9112 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9113 MatCheckPreallocated(mat, 1); 9114 PetscUseTypeMethod(mat, iccfactor, row, info); 9115 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9116 PetscFunctionReturn(PETSC_SUCCESS); 9117 } 9118 9119 /*@ 9120 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9121 ghosted ones. 9122 9123 Not Collective 9124 9125 Input Parameters: 9126 + mat - the matrix 9127 - diag - the diagonal values, including ghost ones 9128 9129 Level: developer 9130 9131 Notes: 9132 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9133 9134 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9135 9136 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9137 @*/ 9138 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9139 { 9140 PetscMPIInt size; 9141 9142 PetscFunctionBegin; 9143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9144 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9145 PetscValidType(mat, 1); 9146 9147 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9148 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9149 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9150 if (size == 1) { 9151 PetscInt n, m; 9152 PetscCall(VecGetSize(diag, &n)); 9153 PetscCall(MatGetSize(mat, NULL, &m)); 9154 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9155 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9156 } else { 9157 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9158 } 9159 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9160 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9161 PetscFunctionReturn(PETSC_SUCCESS); 9162 } 9163 9164 /*@ 9165 MatGetInertia - Gets the inertia from a factored matrix 9166 9167 Collective 9168 9169 Input Parameter: 9170 . mat - the matrix 9171 9172 Output Parameters: 9173 + nneg - number of negative eigenvalues 9174 . nzero - number of zero eigenvalues 9175 - npos - number of positive eigenvalues 9176 9177 Level: advanced 9178 9179 Note: 9180 Matrix must have been factored by `MatCholeskyFactor()` 9181 9182 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9183 @*/ 9184 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9185 { 9186 PetscFunctionBegin; 9187 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9188 PetscValidType(mat, 1); 9189 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9190 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9191 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9192 PetscFunctionReturn(PETSC_SUCCESS); 9193 } 9194 9195 /*@C 9196 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9197 9198 Neighbor-wise Collective 9199 9200 Input Parameters: 9201 + mat - the factored matrix obtained with `MatGetFactor()` 9202 - b - the right-hand-side vectors 9203 9204 Output Parameter: 9205 . x - the result vectors 9206 9207 Level: developer 9208 9209 Note: 9210 The vectors `b` and `x` cannot be the same. I.e., one cannot 9211 call `MatSolves`(A,x,x). 9212 9213 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9214 @*/ 9215 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9216 { 9217 PetscFunctionBegin; 9218 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9219 PetscValidType(mat, 1); 9220 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9221 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9222 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9223 9224 MatCheckPreallocated(mat, 1); 9225 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9226 PetscUseTypeMethod(mat, solves, b, x); 9227 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9228 PetscFunctionReturn(PETSC_SUCCESS); 9229 } 9230 9231 /*@ 9232 MatIsSymmetric - Test whether a matrix is symmetric 9233 9234 Collective 9235 9236 Input Parameters: 9237 + A - the matrix to test 9238 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9239 9240 Output Parameter: 9241 . flg - the result 9242 9243 Level: intermediate 9244 9245 Notes: 9246 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9247 9248 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9249 9250 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9251 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9252 9253 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9254 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9255 @*/ 9256 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9257 { 9258 PetscFunctionBegin; 9259 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9260 PetscAssertPointer(flg, 3); 9261 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9262 else { 9263 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9264 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9265 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9266 } 9267 PetscFunctionReturn(PETSC_SUCCESS); 9268 } 9269 9270 /*@ 9271 MatIsHermitian - Test whether a matrix is Hermitian 9272 9273 Collective 9274 9275 Input Parameters: 9276 + A - the matrix to test 9277 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9278 9279 Output Parameter: 9280 . flg - the result 9281 9282 Level: intermediate 9283 9284 Notes: 9285 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9286 9287 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9288 9289 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9290 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9291 9292 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9293 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9294 @*/ 9295 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9296 { 9297 PetscFunctionBegin; 9298 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9299 PetscAssertPointer(flg, 3); 9300 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9301 else { 9302 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9303 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9304 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9305 } 9306 PetscFunctionReturn(PETSC_SUCCESS); 9307 } 9308 9309 /*@ 9310 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9311 9312 Not Collective 9313 9314 Input Parameter: 9315 . A - the matrix to check 9316 9317 Output Parameters: 9318 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9319 - flg - the result (only valid if set is `PETSC_TRUE`) 9320 9321 Level: advanced 9322 9323 Notes: 9324 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9325 if you want it explicitly checked 9326 9327 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9328 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9329 9330 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9331 @*/ 9332 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9333 { 9334 PetscFunctionBegin; 9335 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9336 PetscAssertPointer(set, 2); 9337 PetscAssertPointer(flg, 3); 9338 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9339 *set = PETSC_TRUE; 9340 *flg = PetscBool3ToBool(A->symmetric); 9341 } else { 9342 *set = PETSC_FALSE; 9343 } 9344 PetscFunctionReturn(PETSC_SUCCESS); 9345 } 9346 9347 /*@ 9348 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9349 9350 Not Collective 9351 9352 Input Parameter: 9353 . A - the matrix to check 9354 9355 Output Parameters: 9356 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9357 - flg - the result (only valid if set is `PETSC_TRUE`) 9358 9359 Level: advanced 9360 9361 Notes: 9362 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9363 9364 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9365 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9366 9367 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9368 @*/ 9369 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9370 { 9371 PetscFunctionBegin; 9372 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9373 PetscAssertPointer(set, 2); 9374 PetscAssertPointer(flg, 3); 9375 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9376 *set = PETSC_TRUE; 9377 *flg = PetscBool3ToBool(A->spd); 9378 } else { 9379 *set = PETSC_FALSE; 9380 } 9381 PetscFunctionReturn(PETSC_SUCCESS); 9382 } 9383 9384 /*@ 9385 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9386 9387 Not Collective 9388 9389 Input Parameter: 9390 . A - the matrix to check 9391 9392 Output Parameters: 9393 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9394 - flg - the result (only valid if set is `PETSC_TRUE`) 9395 9396 Level: advanced 9397 9398 Notes: 9399 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9400 if you want it explicitly checked 9401 9402 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9403 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9404 9405 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9406 @*/ 9407 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9408 { 9409 PetscFunctionBegin; 9410 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9411 PetscAssertPointer(set, 2); 9412 PetscAssertPointer(flg, 3); 9413 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9414 *set = PETSC_TRUE; 9415 *flg = PetscBool3ToBool(A->hermitian); 9416 } else { 9417 *set = PETSC_FALSE; 9418 } 9419 PetscFunctionReturn(PETSC_SUCCESS); 9420 } 9421 9422 /*@ 9423 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9424 9425 Collective 9426 9427 Input Parameter: 9428 . A - the matrix to test 9429 9430 Output Parameter: 9431 . flg - the result 9432 9433 Level: intermediate 9434 9435 Notes: 9436 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9437 9438 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 9439 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9440 9441 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9442 @*/ 9443 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9444 { 9445 PetscFunctionBegin; 9446 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9447 PetscAssertPointer(flg, 2); 9448 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9449 *flg = PetscBool3ToBool(A->structurally_symmetric); 9450 } else { 9451 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9452 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9453 } 9454 PetscFunctionReturn(PETSC_SUCCESS); 9455 } 9456 9457 /*@ 9458 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9459 9460 Not Collective 9461 9462 Input Parameter: 9463 . A - the matrix to check 9464 9465 Output Parameters: 9466 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9467 - flg - the result (only valid if set is PETSC_TRUE) 9468 9469 Level: advanced 9470 9471 Notes: 9472 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 9473 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9474 9475 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9476 9477 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9478 @*/ 9479 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9480 { 9481 PetscFunctionBegin; 9482 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9483 PetscAssertPointer(set, 2); 9484 PetscAssertPointer(flg, 3); 9485 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9486 *set = PETSC_TRUE; 9487 *flg = PetscBool3ToBool(A->structurally_symmetric); 9488 } else { 9489 *set = PETSC_FALSE; 9490 } 9491 PetscFunctionReturn(PETSC_SUCCESS); 9492 } 9493 9494 /*@ 9495 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9496 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9497 9498 Not Collective 9499 9500 Input Parameter: 9501 . mat - the matrix 9502 9503 Output Parameters: 9504 + nstash - the size of the stash 9505 . reallocs - the number of additional mallocs incurred. 9506 . bnstash - the size of the block stash 9507 - breallocs - the number of additional mallocs incurred.in the block stash 9508 9509 Level: advanced 9510 9511 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9512 @*/ 9513 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9514 { 9515 PetscFunctionBegin; 9516 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9517 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9518 PetscFunctionReturn(PETSC_SUCCESS); 9519 } 9520 9521 /*@ 9522 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9523 parallel layout, `PetscLayout` for rows and columns 9524 9525 Collective 9526 9527 Input Parameter: 9528 . mat - the matrix 9529 9530 Output Parameters: 9531 + right - (optional) vector that the matrix can be multiplied against 9532 - left - (optional) vector that the matrix vector product can be stored in 9533 9534 Level: advanced 9535 9536 Notes: 9537 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()`. 9538 9539 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9540 9541 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9542 @*/ 9543 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9544 { 9545 PetscFunctionBegin; 9546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9547 PetscValidType(mat, 1); 9548 if (mat->ops->getvecs) { 9549 PetscUseTypeMethod(mat, getvecs, right, left); 9550 } else { 9551 if (right) { 9552 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9553 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9554 PetscCall(VecSetType(*right, mat->defaultvectype)); 9555 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9556 if (mat->boundtocpu && mat->bindingpropagates) { 9557 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9558 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9559 } 9560 #endif 9561 } 9562 if (left) { 9563 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9564 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9565 PetscCall(VecSetType(*left, mat->defaultvectype)); 9566 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9567 if (mat->boundtocpu && mat->bindingpropagates) { 9568 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9569 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9570 } 9571 #endif 9572 } 9573 } 9574 PetscFunctionReturn(PETSC_SUCCESS); 9575 } 9576 9577 /*@ 9578 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9579 with default values. 9580 9581 Not Collective 9582 9583 Input Parameter: 9584 . info - the `MatFactorInfo` data structure 9585 9586 Level: developer 9587 9588 Notes: 9589 The solvers are generally used through the `KSP` and `PC` objects, for example 9590 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9591 9592 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9593 9594 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9595 @*/ 9596 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9597 { 9598 PetscFunctionBegin; 9599 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9600 PetscFunctionReturn(PETSC_SUCCESS); 9601 } 9602 9603 /*@ 9604 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9605 9606 Collective 9607 9608 Input Parameters: 9609 + mat - the factored matrix 9610 - is - the index set defining the Schur indices (0-based) 9611 9612 Level: advanced 9613 9614 Notes: 9615 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9616 9617 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9618 9619 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9620 9621 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9622 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9623 @*/ 9624 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9625 { 9626 PetscErrorCode (*f)(Mat, IS); 9627 9628 PetscFunctionBegin; 9629 PetscValidType(mat, 1); 9630 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9631 PetscValidType(is, 2); 9632 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9633 PetscCheckSameComm(mat, 1, is, 2); 9634 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9635 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9636 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9637 PetscCall(MatDestroy(&mat->schur)); 9638 PetscCall((*f)(mat, is)); 9639 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9640 PetscFunctionReturn(PETSC_SUCCESS); 9641 } 9642 9643 /*@ 9644 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9645 9646 Logically Collective 9647 9648 Input Parameters: 9649 + F - the factored matrix obtained by calling `MatGetFactor()` 9650 . S - location where to return the Schur complement, can be `NULL` 9651 - status - the status of the Schur complement matrix, can be `NULL` 9652 9653 Level: advanced 9654 9655 Notes: 9656 You must call `MatFactorSetSchurIS()` before calling this routine. 9657 9658 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9659 9660 The routine provides a copy of the Schur matrix stored within the solver data structures. 9661 The caller must destroy the object when it is no longer needed. 9662 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9663 9664 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) 9665 9666 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9667 9668 Developer Note: 9669 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9670 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9671 9672 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9673 @*/ 9674 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9675 { 9676 PetscFunctionBegin; 9677 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9678 if (S) PetscAssertPointer(S, 2); 9679 if (status) PetscAssertPointer(status, 3); 9680 if (S) { 9681 PetscErrorCode (*f)(Mat, Mat *); 9682 9683 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9684 if (f) { 9685 PetscCall((*f)(F, S)); 9686 } else { 9687 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9688 } 9689 } 9690 if (status) *status = F->schur_status; 9691 PetscFunctionReturn(PETSC_SUCCESS); 9692 } 9693 9694 /*@ 9695 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9696 9697 Logically Collective 9698 9699 Input Parameters: 9700 + F - the factored matrix obtained by calling `MatGetFactor()` 9701 . S - location where to return the Schur complement, can be `NULL` 9702 - status - the status of the Schur complement matrix, can be `NULL` 9703 9704 Level: advanced 9705 9706 Notes: 9707 You must call `MatFactorSetSchurIS()` before calling this routine. 9708 9709 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9710 9711 The routine returns a the Schur Complement stored within the data structures of the solver. 9712 9713 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9714 9715 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9716 9717 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9718 9719 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9720 9721 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9722 @*/ 9723 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9724 { 9725 PetscFunctionBegin; 9726 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9727 if (S) { 9728 PetscAssertPointer(S, 2); 9729 *S = F->schur; 9730 } 9731 if (status) { 9732 PetscAssertPointer(status, 3); 9733 *status = F->schur_status; 9734 } 9735 PetscFunctionReturn(PETSC_SUCCESS); 9736 } 9737 9738 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9739 { 9740 Mat S = F->schur; 9741 9742 PetscFunctionBegin; 9743 switch (F->schur_status) { 9744 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9745 case MAT_FACTOR_SCHUR_INVERTED: 9746 if (S) { 9747 S->ops->solve = NULL; 9748 S->ops->matsolve = NULL; 9749 S->ops->solvetranspose = NULL; 9750 S->ops->matsolvetranspose = NULL; 9751 S->ops->solveadd = NULL; 9752 S->ops->solvetransposeadd = NULL; 9753 S->factortype = MAT_FACTOR_NONE; 9754 PetscCall(PetscFree(S->solvertype)); 9755 } 9756 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9757 break; 9758 default: 9759 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9760 } 9761 PetscFunctionReturn(PETSC_SUCCESS); 9762 } 9763 9764 /*@ 9765 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9766 9767 Logically Collective 9768 9769 Input Parameters: 9770 + F - the factored matrix obtained by calling `MatGetFactor()` 9771 . S - location where the Schur complement is stored 9772 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9773 9774 Level: advanced 9775 9776 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9777 @*/ 9778 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9779 { 9780 PetscFunctionBegin; 9781 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9782 if (S) { 9783 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9784 *S = NULL; 9785 } 9786 F->schur_status = status; 9787 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9788 PetscFunctionReturn(PETSC_SUCCESS); 9789 } 9790 9791 /*@ 9792 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9793 9794 Logically Collective 9795 9796 Input Parameters: 9797 + F - the factored matrix obtained by calling `MatGetFactor()` 9798 . rhs - location where the right-hand side of the Schur complement system is stored 9799 - sol - location where the solution of the Schur complement system has to be returned 9800 9801 Level: advanced 9802 9803 Notes: 9804 The sizes of the vectors should match the size of the Schur complement 9805 9806 Must be called after `MatFactorSetSchurIS()` 9807 9808 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9809 @*/ 9810 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9811 { 9812 PetscFunctionBegin; 9813 PetscValidType(F, 1); 9814 PetscValidType(rhs, 2); 9815 PetscValidType(sol, 3); 9816 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9817 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9818 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9819 PetscCheckSameComm(F, 1, rhs, 2); 9820 PetscCheckSameComm(F, 1, sol, 3); 9821 PetscCall(MatFactorFactorizeSchurComplement(F)); 9822 switch (F->schur_status) { 9823 case MAT_FACTOR_SCHUR_FACTORED: 9824 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9825 break; 9826 case MAT_FACTOR_SCHUR_INVERTED: 9827 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9828 break; 9829 default: 9830 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9831 } 9832 PetscFunctionReturn(PETSC_SUCCESS); 9833 } 9834 9835 /*@ 9836 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9837 9838 Logically Collective 9839 9840 Input Parameters: 9841 + F - the factored matrix obtained by calling `MatGetFactor()` 9842 . rhs - location where the right-hand side of the Schur complement system is stored 9843 - sol - location where the solution of the Schur complement system has to be returned 9844 9845 Level: advanced 9846 9847 Notes: 9848 The sizes of the vectors should match the size of the Schur complement 9849 9850 Must be called after `MatFactorSetSchurIS()` 9851 9852 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9853 @*/ 9854 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9855 { 9856 PetscFunctionBegin; 9857 PetscValidType(F, 1); 9858 PetscValidType(rhs, 2); 9859 PetscValidType(sol, 3); 9860 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9861 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9862 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9863 PetscCheckSameComm(F, 1, rhs, 2); 9864 PetscCheckSameComm(F, 1, sol, 3); 9865 PetscCall(MatFactorFactorizeSchurComplement(F)); 9866 switch (F->schur_status) { 9867 case MAT_FACTOR_SCHUR_FACTORED: 9868 PetscCall(MatSolve(F->schur, rhs, sol)); 9869 break; 9870 case MAT_FACTOR_SCHUR_INVERTED: 9871 PetscCall(MatMult(F->schur, rhs, sol)); 9872 break; 9873 default: 9874 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9875 } 9876 PetscFunctionReturn(PETSC_SUCCESS); 9877 } 9878 9879 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9880 #if PetscDefined(HAVE_CUDA) 9881 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9882 #endif 9883 9884 /* Schur status updated in the interface */ 9885 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9886 { 9887 Mat S = F->schur; 9888 9889 PetscFunctionBegin; 9890 if (S) { 9891 PetscMPIInt size; 9892 PetscBool isdense, isdensecuda; 9893 9894 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9895 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9896 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9897 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9898 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9899 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9900 if (isdense) { 9901 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9902 } else if (isdensecuda) { 9903 #if defined(PETSC_HAVE_CUDA) 9904 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9905 #endif 9906 } 9907 // HIP?????????????? 9908 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9909 } 9910 PetscFunctionReturn(PETSC_SUCCESS); 9911 } 9912 9913 /*@ 9914 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9915 9916 Logically Collective 9917 9918 Input Parameter: 9919 . F - the factored matrix obtained by calling `MatGetFactor()` 9920 9921 Level: advanced 9922 9923 Notes: 9924 Must be called after `MatFactorSetSchurIS()`. 9925 9926 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9927 9928 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9929 @*/ 9930 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9931 { 9932 PetscFunctionBegin; 9933 PetscValidType(F, 1); 9934 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9935 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9936 PetscCall(MatFactorFactorizeSchurComplement(F)); 9937 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9938 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9939 PetscFunctionReturn(PETSC_SUCCESS); 9940 } 9941 9942 /*@ 9943 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9944 9945 Logically Collective 9946 9947 Input Parameter: 9948 . F - the factored matrix obtained by calling `MatGetFactor()` 9949 9950 Level: advanced 9951 9952 Note: 9953 Must be called after `MatFactorSetSchurIS()` 9954 9955 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9956 @*/ 9957 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9958 { 9959 MatFactorInfo info; 9960 9961 PetscFunctionBegin; 9962 PetscValidType(F, 1); 9963 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9964 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9965 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9966 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9967 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9968 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9969 } else { 9970 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9971 } 9972 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9973 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9974 PetscFunctionReturn(PETSC_SUCCESS); 9975 } 9976 9977 /*@ 9978 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9979 9980 Neighbor-wise Collective 9981 9982 Input Parameters: 9983 + A - the matrix 9984 . P - the projection matrix 9985 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9986 - 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 9987 if the result is a dense matrix this is irrelevant 9988 9989 Output Parameter: 9990 . C - the product matrix 9991 9992 Level: intermediate 9993 9994 Notes: 9995 C will be created and must be destroyed by the user with `MatDestroy()`. 9996 9997 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9998 9999 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10000 10001 Developer Note: 10002 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10003 10004 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10005 @*/ 10006 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10007 { 10008 PetscFunctionBegin; 10009 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10010 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10011 10012 if (scall == MAT_INITIAL_MATRIX) { 10013 PetscCall(MatProductCreate(A, P, NULL, C)); 10014 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10015 PetscCall(MatProductSetAlgorithm(*C, "default")); 10016 PetscCall(MatProductSetFill(*C, fill)); 10017 10018 (*C)->product->api_user = PETSC_TRUE; 10019 PetscCall(MatProductSetFromOptions(*C)); 10020 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); 10021 PetscCall(MatProductSymbolic(*C)); 10022 } else { /* scall == MAT_REUSE_MATRIX */ 10023 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10024 } 10025 10026 PetscCall(MatProductNumeric(*C)); 10027 (*C)->symmetric = A->symmetric; 10028 (*C)->spd = A->spd; 10029 PetscFunctionReturn(PETSC_SUCCESS); 10030 } 10031 10032 /*@ 10033 MatRARt - Creates the matrix product $C = R * A * R^T$ 10034 10035 Neighbor-wise Collective 10036 10037 Input Parameters: 10038 + A - the matrix 10039 . R - the projection matrix 10040 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10041 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10042 if the result is a dense matrix this is irrelevant 10043 10044 Output Parameter: 10045 . C - the product matrix 10046 10047 Level: intermediate 10048 10049 Notes: 10050 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10051 10052 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10053 10054 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10055 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10056 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10057 We recommend using `MatPtAP()` when possible. 10058 10059 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10060 10061 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10062 @*/ 10063 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10064 { 10065 PetscFunctionBegin; 10066 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10067 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10068 10069 if (scall == MAT_INITIAL_MATRIX) { 10070 PetscCall(MatProductCreate(A, R, NULL, C)); 10071 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10072 PetscCall(MatProductSetAlgorithm(*C, "default")); 10073 PetscCall(MatProductSetFill(*C, fill)); 10074 10075 (*C)->product->api_user = PETSC_TRUE; 10076 PetscCall(MatProductSetFromOptions(*C)); 10077 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); 10078 PetscCall(MatProductSymbolic(*C)); 10079 } else { /* scall == MAT_REUSE_MATRIX */ 10080 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10081 } 10082 10083 PetscCall(MatProductNumeric(*C)); 10084 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10085 PetscFunctionReturn(PETSC_SUCCESS); 10086 } 10087 10088 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10089 { 10090 PetscBool flg = PETSC_TRUE; 10091 10092 PetscFunctionBegin; 10093 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10094 if (scall == MAT_INITIAL_MATRIX) { 10095 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10096 PetscCall(MatProductCreate(A, B, NULL, C)); 10097 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10098 PetscCall(MatProductSetFill(*C, fill)); 10099 } else { /* scall == MAT_REUSE_MATRIX */ 10100 Mat_Product *product = (*C)->product; 10101 10102 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10103 if (flg && product && product->type != ptype) { 10104 PetscCall(MatProductClear(*C)); 10105 product = NULL; 10106 } 10107 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10108 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10109 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10110 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10111 product = (*C)->product; 10112 product->fill = fill; 10113 product->clear = PETSC_TRUE; 10114 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10115 flg = PETSC_FALSE; 10116 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10117 } 10118 } 10119 if (flg) { 10120 (*C)->product->api_user = PETSC_TRUE; 10121 PetscCall(MatProductSetType(*C, ptype)); 10122 PetscCall(MatProductSetFromOptions(*C)); 10123 PetscCall(MatProductSymbolic(*C)); 10124 } 10125 PetscCall(MatProductNumeric(*C)); 10126 PetscFunctionReturn(PETSC_SUCCESS); 10127 } 10128 10129 /*@ 10130 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10131 10132 Neighbor-wise Collective 10133 10134 Input Parameters: 10135 + A - the left matrix 10136 . B - the right matrix 10137 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10138 - 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 10139 if the result is a dense matrix this is irrelevant 10140 10141 Output Parameter: 10142 . C - the product matrix 10143 10144 Notes: 10145 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10146 10147 `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 10148 call to this function with `MAT_INITIAL_MATRIX`. 10149 10150 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10151 10152 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`, 10153 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10154 10155 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10156 10157 Example of Usage: 10158 .vb 10159 MatProductCreate(A,B,NULL,&C); 10160 MatProductSetType(C,MATPRODUCT_AB); 10161 MatProductSymbolic(C); 10162 MatProductNumeric(C); // compute C=A * B 10163 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10164 MatProductNumeric(C); 10165 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10166 MatProductNumeric(C); 10167 .ve 10168 10169 Level: intermediate 10170 10171 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10172 @*/ 10173 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10174 { 10175 PetscFunctionBegin; 10176 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10177 PetscFunctionReturn(PETSC_SUCCESS); 10178 } 10179 10180 /*@ 10181 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10182 10183 Neighbor-wise Collective 10184 10185 Input Parameters: 10186 + A - the left matrix 10187 . B - the right matrix 10188 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10189 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10190 10191 Output Parameter: 10192 . C - the product matrix 10193 10194 Options Database Key: 10195 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10196 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10197 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10198 10199 Level: intermediate 10200 10201 Notes: 10202 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10203 10204 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10205 10206 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10207 actually needed. 10208 10209 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10210 and for pairs of `MATMPIDENSE` matrices. 10211 10212 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10213 10214 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10215 10216 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10217 @*/ 10218 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10219 { 10220 PetscFunctionBegin; 10221 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10222 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10223 PetscFunctionReturn(PETSC_SUCCESS); 10224 } 10225 10226 /*@ 10227 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10228 10229 Neighbor-wise Collective 10230 10231 Input Parameters: 10232 + A - the left matrix 10233 . B - the right matrix 10234 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10235 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10236 10237 Output Parameter: 10238 . C - the product matrix 10239 10240 Level: intermediate 10241 10242 Notes: 10243 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10244 10245 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10246 10247 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10248 10249 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10250 actually needed. 10251 10252 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10253 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10254 10255 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10256 10257 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10258 @*/ 10259 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10260 { 10261 PetscFunctionBegin; 10262 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10263 PetscFunctionReturn(PETSC_SUCCESS); 10264 } 10265 10266 /*@ 10267 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10268 10269 Neighbor-wise Collective 10270 10271 Input Parameters: 10272 + A - the left matrix 10273 . B - the middle matrix 10274 . C - the right matrix 10275 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10276 - 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 10277 if the result is a dense matrix this is irrelevant 10278 10279 Output Parameter: 10280 . D - the product matrix 10281 10282 Level: intermediate 10283 10284 Notes: 10285 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10286 10287 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10288 10289 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10290 10291 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10292 actually needed. 10293 10294 If you have many matrices with the same non-zero structure to multiply, you 10295 should use `MAT_REUSE_MATRIX` in all calls but the first 10296 10297 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10298 10299 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10300 @*/ 10301 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10302 { 10303 PetscFunctionBegin; 10304 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10305 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10306 10307 if (scall == MAT_INITIAL_MATRIX) { 10308 PetscCall(MatProductCreate(A, B, C, D)); 10309 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10310 PetscCall(MatProductSetAlgorithm(*D, "default")); 10311 PetscCall(MatProductSetFill(*D, fill)); 10312 10313 (*D)->product->api_user = PETSC_TRUE; 10314 PetscCall(MatProductSetFromOptions(*D)); 10315 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, 10316 ((PetscObject)C)->type_name); 10317 PetscCall(MatProductSymbolic(*D)); 10318 } else { /* user may change input matrices when REUSE */ 10319 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10320 } 10321 PetscCall(MatProductNumeric(*D)); 10322 PetscFunctionReturn(PETSC_SUCCESS); 10323 } 10324 10325 /*@ 10326 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10327 10328 Collective 10329 10330 Input Parameters: 10331 + mat - the matrix 10332 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10333 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10334 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10335 10336 Output Parameter: 10337 . matredundant - redundant matrix 10338 10339 Level: advanced 10340 10341 Notes: 10342 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10343 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10344 10345 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10346 calling it. 10347 10348 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10349 10350 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10351 @*/ 10352 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10353 { 10354 MPI_Comm comm; 10355 PetscMPIInt size; 10356 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10357 Mat_Redundant *redund = NULL; 10358 PetscSubcomm psubcomm = NULL; 10359 MPI_Comm subcomm_in = subcomm; 10360 Mat *matseq; 10361 IS isrow, iscol; 10362 PetscBool newsubcomm = PETSC_FALSE; 10363 10364 PetscFunctionBegin; 10365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10366 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10367 PetscAssertPointer(*matredundant, 5); 10368 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10369 } 10370 10371 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10372 if (size == 1 || nsubcomm == 1) { 10373 if (reuse == MAT_INITIAL_MATRIX) { 10374 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10375 } else { 10376 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"); 10377 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10378 } 10379 PetscFunctionReturn(PETSC_SUCCESS); 10380 } 10381 10382 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10383 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10384 MatCheckPreallocated(mat, 1); 10385 10386 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10387 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10388 /* create psubcomm, then get subcomm */ 10389 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10390 PetscCallMPI(MPI_Comm_size(comm, &size)); 10391 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10392 10393 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10394 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10395 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10396 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10397 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10398 newsubcomm = PETSC_TRUE; 10399 PetscCall(PetscSubcommDestroy(&psubcomm)); 10400 } 10401 10402 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10403 if (reuse == MAT_INITIAL_MATRIX) { 10404 mloc_sub = PETSC_DECIDE; 10405 nloc_sub = PETSC_DECIDE; 10406 if (bs < 1) { 10407 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10408 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10409 } else { 10410 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10411 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10412 } 10413 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10414 rstart = rend - mloc_sub; 10415 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10416 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10417 PetscCall(ISSetIdentity(iscol)); 10418 } else { /* reuse == MAT_REUSE_MATRIX */ 10419 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"); 10420 /* retrieve subcomm */ 10421 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10422 redund = (*matredundant)->redundant; 10423 isrow = redund->isrow; 10424 iscol = redund->iscol; 10425 matseq = redund->matseq; 10426 } 10427 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10428 10429 /* get matredundant over subcomm */ 10430 if (reuse == MAT_INITIAL_MATRIX) { 10431 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10432 10433 /* create a supporting struct and attach it to C for reuse */ 10434 PetscCall(PetscNew(&redund)); 10435 (*matredundant)->redundant = redund; 10436 redund->isrow = isrow; 10437 redund->iscol = iscol; 10438 redund->matseq = matseq; 10439 if (newsubcomm) { 10440 redund->subcomm = subcomm; 10441 } else { 10442 redund->subcomm = MPI_COMM_NULL; 10443 } 10444 } else { 10445 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10446 } 10447 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10448 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10449 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10450 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10451 } 10452 #endif 10453 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10454 PetscFunctionReturn(PETSC_SUCCESS); 10455 } 10456 10457 /*@C 10458 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10459 a given `Mat`. Each submatrix can span multiple procs. 10460 10461 Collective 10462 10463 Input Parameters: 10464 + mat - the matrix 10465 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10466 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10467 10468 Output Parameter: 10469 . subMat - parallel sub-matrices each spanning a given `subcomm` 10470 10471 Level: advanced 10472 10473 Notes: 10474 The submatrix partition across processors is dictated by `subComm` a 10475 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10476 is not restricted to be grouped with consecutive original MPI processes. 10477 10478 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10479 map directly to the layout of the original matrix [wrt the local 10480 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10481 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10482 the `subMat`. However the offDiagMat looses some columns - and this is 10483 reconstructed with `MatSetValues()` 10484 10485 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10486 10487 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10488 @*/ 10489 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10490 { 10491 PetscMPIInt commsize, subCommSize; 10492 10493 PetscFunctionBegin; 10494 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10495 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10496 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10497 10498 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"); 10499 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10500 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10501 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10502 PetscFunctionReturn(PETSC_SUCCESS); 10503 } 10504 10505 /*@ 10506 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10507 10508 Not Collective 10509 10510 Input Parameters: 10511 + mat - matrix to extract local submatrix from 10512 . isrow - local row indices for submatrix 10513 - iscol - local column indices for submatrix 10514 10515 Output Parameter: 10516 . submat - the submatrix 10517 10518 Level: intermediate 10519 10520 Notes: 10521 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10522 10523 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10524 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10525 10526 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10527 `MatSetValuesBlockedLocal()` will also be implemented. 10528 10529 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10530 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10531 10532 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10533 @*/ 10534 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10535 { 10536 PetscFunctionBegin; 10537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10538 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10539 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10540 PetscCheckSameComm(isrow, 2, iscol, 3); 10541 PetscAssertPointer(submat, 4); 10542 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10543 10544 if (mat->ops->getlocalsubmatrix) { 10545 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10546 } else { 10547 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10548 } 10549 PetscFunctionReturn(PETSC_SUCCESS); 10550 } 10551 10552 /*@ 10553 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10554 10555 Not Collective 10556 10557 Input Parameters: 10558 + mat - matrix to extract local submatrix from 10559 . isrow - local row indices for submatrix 10560 . iscol - local column indices for submatrix 10561 - submat - the submatrix 10562 10563 Level: intermediate 10564 10565 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10566 @*/ 10567 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10568 { 10569 PetscFunctionBegin; 10570 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10571 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10572 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10573 PetscCheckSameComm(isrow, 2, iscol, 3); 10574 PetscAssertPointer(submat, 4); 10575 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10576 10577 if (mat->ops->restorelocalsubmatrix) { 10578 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10579 } else { 10580 PetscCall(MatDestroy(submat)); 10581 } 10582 *submat = NULL; 10583 PetscFunctionReturn(PETSC_SUCCESS); 10584 } 10585 10586 /*@ 10587 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10588 10589 Collective 10590 10591 Input Parameter: 10592 . mat - the matrix 10593 10594 Output Parameter: 10595 . is - if any rows have zero diagonals this contains the list of them 10596 10597 Level: developer 10598 10599 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10600 @*/ 10601 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10602 { 10603 PetscFunctionBegin; 10604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10605 PetscValidType(mat, 1); 10606 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10607 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10608 10609 if (!mat->ops->findzerodiagonals) { 10610 Vec diag; 10611 const PetscScalar *a; 10612 PetscInt *rows; 10613 PetscInt rStart, rEnd, r, nrow = 0; 10614 10615 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10616 PetscCall(MatGetDiagonal(mat, diag)); 10617 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10618 PetscCall(VecGetArrayRead(diag, &a)); 10619 for (r = 0; r < rEnd - rStart; ++r) 10620 if (a[r] == 0.0) ++nrow; 10621 PetscCall(PetscMalloc1(nrow, &rows)); 10622 nrow = 0; 10623 for (r = 0; r < rEnd - rStart; ++r) 10624 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10625 PetscCall(VecRestoreArrayRead(diag, &a)); 10626 PetscCall(VecDestroy(&diag)); 10627 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10628 } else { 10629 PetscUseTypeMethod(mat, findzerodiagonals, is); 10630 } 10631 PetscFunctionReturn(PETSC_SUCCESS); 10632 } 10633 10634 /*@ 10635 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10636 10637 Collective 10638 10639 Input Parameter: 10640 . mat - the matrix 10641 10642 Output Parameter: 10643 . is - contains the list of rows with off block diagonal entries 10644 10645 Level: developer 10646 10647 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10648 @*/ 10649 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10650 { 10651 PetscFunctionBegin; 10652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10653 PetscValidType(mat, 1); 10654 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10655 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10656 10657 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10658 PetscFunctionReturn(PETSC_SUCCESS); 10659 } 10660 10661 /*@C 10662 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10663 10664 Collective; No Fortran Support 10665 10666 Input Parameter: 10667 . mat - the matrix 10668 10669 Output Parameter: 10670 . values - the block inverses in column major order (FORTRAN-like) 10671 10672 Level: advanced 10673 10674 Notes: 10675 The size of the blocks is determined by the block size of the matrix. 10676 10677 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10678 10679 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10680 10681 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10682 @*/ 10683 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10684 { 10685 PetscFunctionBegin; 10686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10687 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10688 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10689 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10690 PetscFunctionReturn(PETSC_SUCCESS); 10691 } 10692 10693 /*@ 10694 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10695 10696 Collective; No Fortran Support 10697 10698 Input Parameters: 10699 + mat - the matrix 10700 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10701 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10702 10703 Output Parameter: 10704 . values - the block inverses in column major order (FORTRAN-like) 10705 10706 Level: advanced 10707 10708 Notes: 10709 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10710 10711 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10712 10713 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10714 @*/ 10715 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10716 { 10717 PetscFunctionBegin; 10718 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10719 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10720 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10721 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10722 PetscFunctionReturn(PETSC_SUCCESS); 10723 } 10724 10725 /*@ 10726 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10727 10728 Collective 10729 10730 Input Parameters: 10731 + A - the matrix 10732 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10733 10734 Level: advanced 10735 10736 Note: 10737 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10738 10739 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10740 @*/ 10741 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10742 { 10743 const PetscScalar *vals; 10744 PetscInt *dnnz; 10745 PetscInt m, rstart, rend, bs, i, j; 10746 10747 PetscFunctionBegin; 10748 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10749 PetscCall(MatGetBlockSize(A, &bs)); 10750 PetscCall(MatGetLocalSize(A, &m, NULL)); 10751 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10752 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10753 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10754 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10755 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10756 PetscCall(PetscFree(dnnz)); 10757 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10758 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10759 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10760 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10761 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10762 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10763 PetscFunctionReturn(PETSC_SUCCESS); 10764 } 10765 10766 /*@ 10767 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10768 via `MatTransposeColoringCreate()`. 10769 10770 Collective 10771 10772 Input Parameter: 10773 . c - coloring context 10774 10775 Level: intermediate 10776 10777 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10778 @*/ 10779 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10780 { 10781 MatTransposeColoring matcolor = *c; 10782 10783 PetscFunctionBegin; 10784 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10785 if (--((PetscObject)matcolor)->refct > 0) { 10786 matcolor = NULL; 10787 PetscFunctionReturn(PETSC_SUCCESS); 10788 } 10789 10790 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10791 PetscCall(PetscFree(matcolor->rows)); 10792 PetscCall(PetscFree(matcolor->den2sp)); 10793 PetscCall(PetscFree(matcolor->colorforcol)); 10794 PetscCall(PetscFree(matcolor->columns)); 10795 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10796 PetscCall(PetscHeaderDestroy(c)); 10797 PetscFunctionReturn(PETSC_SUCCESS); 10798 } 10799 10800 /*@ 10801 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10802 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10803 `MatTransposeColoring` to sparse `B`. 10804 10805 Collective 10806 10807 Input Parameters: 10808 + coloring - coloring context created with `MatTransposeColoringCreate()` 10809 - B - sparse matrix 10810 10811 Output Parameter: 10812 . Btdense - dense matrix $B^T$ 10813 10814 Level: developer 10815 10816 Note: 10817 These are used internally for some implementations of `MatRARt()` 10818 10819 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10820 @*/ 10821 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10822 { 10823 PetscFunctionBegin; 10824 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10825 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10826 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10827 10828 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10829 PetscFunctionReturn(PETSC_SUCCESS); 10830 } 10831 10832 /*@ 10833 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10834 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10835 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10836 $C_{sp}$ from $C_{den}$. 10837 10838 Collective 10839 10840 Input Parameters: 10841 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10842 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10843 10844 Output Parameter: 10845 . Csp - sparse matrix 10846 10847 Level: developer 10848 10849 Note: 10850 These are used internally for some implementations of `MatRARt()` 10851 10852 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10853 @*/ 10854 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10855 { 10856 PetscFunctionBegin; 10857 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10858 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10859 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10860 10861 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10862 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10863 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10864 PetscFunctionReturn(PETSC_SUCCESS); 10865 } 10866 10867 /*@ 10868 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10869 10870 Collective 10871 10872 Input Parameters: 10873 + mat - the matrix product C 10874 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10875 10876 Output Parameter: 10877 . color - the new coloring context 10878 10879 Level: intermediate 10880 10881 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10882 `MatTransColoringApplyDenToSp()` 10883 @*/ 10884 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10885 { 10886 MatTransposeColoring c; 10887 MPI_Comm comm; 10888 10889 PetscFunctionBegin; 10890 PetscAssertPointer(color, 3); 10891 10892 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10893 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10894 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10895 c->ctype = iscoloring->ctype; 10896 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10897 *color = c; 10898 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10899 PetscFunctionReturn(PETSC_SUCCESS); 10900 } 10901 10902 /*@ 10903 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10904 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10905 10906 Not Collective 10907 10908 Input Parameter: 10909 . mat - the matrix 10910 10911 Output Parameter: 10912 . state - the current state 10913 10914 Level: intermediate 10915 10916 Notes: 10917 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10918 different matrices 10919 10920 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10921 10922 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10923 10924 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10925 @*/ 10926 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10927 { 10928 PetscFunctionBegin; 10929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10930 *state = mat->nonzerostate; 10931 PetscFunctionReturn(PETSC_SUCCESS); 10932 } 10933 10934 /*@ 10935 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10936 matrices from each processor 10937 10938 Collective 10939 10940 Input Parameters: 10941 + comm - the communicators the parallel matrix will live on 10942 . seqmat - the input sequential matrices 10943 . n - number of local columns (or `PETSC_DECIDE`) 10944 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10945 10946 Output Parameter: 10947 . mpimat - the parallel matrix generated 10948 10949 Level: developer 10950 10951 Note: 10952 The number of columns of the matrix in EACH processor MUST be the same. 10953 10954 .seealso: [](ch_matrices), `Mat` 10955 @*/ 10956 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10957 { 10958 PetscMPIInt size; 10959 10960 PetscFunctionBegin; 10961 PetscCallMPI(MPI_Comm_size(comm, &size)); 10962 if (size == 1) { 10963 if (reuse == MAT_INITIAL_MATRIX) { 10964 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10965 } else { 10966 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10967 } 10968 PetscFunctionReturn(PETSC_SUCCESS); 10969 } 10970 10971 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"); 10972 10973 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10974 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10975 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10976 PetscFunctionReturn(PETSC_SUCCESS); 10977 } 10978 10979 /*@ 10980 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10981 10982 Collective 10983 10984 Input Parameters: 10985 + A - the matrix to create subdomains from 10986 - N - requested number of subdomains 10987 10988 Output Parameters: 10989 + n - number of subdomains resulting on this MPI process 10990 - iss - `IS` list with indices of subdomains on this MPI process 10991 10992 Level: advanced 10993 10994 Note: 10995 The number of subdomains must be smaller than the communicator size 10996 10997 .seealso: [](ch_matrices), `Mat`, `IS` 10998 @*/ 10999 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11000 { 11001 MPI_Comm comm, subcomm; 11002 PetscMPIInt size, rank, color; 11003 PetscInt rstart, rend, k; 11004 11005 PetscFunctionBegin; 11006 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11007 PetscCallMPI(MPI_Comm_size(comm, &size)); 11008 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11009 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); 11010 *n = 1; 11011 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11012 color = rank / k; 11013 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11014 PetscCall(PetscMalloc1(1, iss)); 11015 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11016 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11017 PetscCallMPI(MPI_Comm_free(&subcomm)); 11018 PetscFunctionReturn(PETSC_SUCCESS); 11019 } 11020 11021 /*@ 11022 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11023 11024 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11025 If they are not the same, uses `MatMatMatMult()`. 11026 11027 Once the coarse grid problem is constructed, correct for interpolation operators 11028 that are not of full rank, which can legitimately happen in the case of non-nested 11029 geometric multigrid. 11030 11031 Input Parameters: 11032 + restrct - restriction operator 11033 . dA - fine grid matrix 11034 . interpolate - interpolation operator 11035 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11036 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11037 11038 Output Parameter: 11039 . A - the Galerkin coarse matrix 11040 11041 Options Database Key: 11042 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11043 11044 Level: developer 11045 11046 Note: 11047 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11048 11049 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11050 @*/ 11051 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11052 { 11053 IS zerorows; 11054 Vec diag; 11055 11056 PetscFunctionBegin; 11057 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11058 /* Construct the coarse grid matrix */ 11059 if (interpolate == restrct) { 11060 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11061 } else { 11062 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11063 } 11064 11065 /* If the interpolation matrix is not of full rank, A will have zero rows. 11066 This can legitimately happen in the case of non-nested geometric multigrid. 11067 In that event, we set the rows of the matrix to the rows of the identity, 11068 ignoring the equations (as the RHS will also be zero). */ 11069 11070 PetscCall(MatFindZeroRows(*A, &zerorows)); 11071 11072 if (zerorows != NULL) { /* if there are any zero rows */ 11073 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11074 PetscCall(MatGetDiagonal(*A, diag)); 11075 PetscCall(VecISSet(diag, zerorows, 1.0)); 11076 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11077 PetscCall(VecDestroy(&diag)); 11078 PetscCall(ISDestroy(&zerorows)); 11079 } 11080 PetscFunctionReturn(PETSC_SUCCESS); 11081 } 11082 11083 /*@C 11084 MatSetOperation - Allows user to set a matrix operation for any matrix type 11085 11086 Logically Collective 11087 11088 Input Parameters: 11089 + mat - the matrix 11090 . op - the name of the operation 11091 - f - the function that provides the operation 11092 11093 Level: developer 11094 11095 Example Usage: 11096 .vb 11097 extern PetscErrorCode usermult(Mat, Vec, Vec); 11098 11099 PetscCall(MatCreateXXX(comm, ..., &A)); 11100 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11101 .ve 11102 11103 Notes: 11104 See the file `include/petscmat.h` for a complete list of matrix 11105 operations, which all have the form MATOP_<OPERATION>, where 11106 <OPERATION> is the name (in all capital letters) of the 11107 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11108 11109 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11110 sequence as the usual matrix interface routines, since they 11111 are intended to be accessed via the usual matrix interface 11112 routines, e.g., 11113 .vb 11114 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11115 .ve 11116 11117 In particular each function MUST return `PETSC_SUCCESS` on success and 11118 nonzero on failure. 11119 11120 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11121 11122 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11123 @*/ 11124 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11125 { 11126 PetscFunctionBegin; 11127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11128 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11129 (((void (**)(void))mat->ops)[op]) = f; 11130 PetscFunctionReturn(PETSC_SUCCESS); 11131 } 11132 11133 /*@C 11134 MatGetOperation - Gets a matrix operation for any matrix type. 11135 11136 Not Collective 11137 11138 Input Parameters: 11139 + mat - the matrix 11140 - op - the name of the operation 11141 11142 Output Parameter: 11143 . f - the function that provides the operation 11144 11145 Level: developer 11146 11147 Example Usage: 11148 .vb 11149 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11150 11151 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11152 .ve 11153 11154 Notes: 11155 See the file include/petscmat.h for a complete list of matrix 11156 operations, which all have the form MATOP_<OPERATION>, where 11157 <OPERATION> is the name (in all capital letters) of the 11158 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11159 11160 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11161 11162 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11163 @*/ 11164 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11165 { 11166 PetscFunctionBegin; 11167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11168 *f = (((void (**)(void))mat->ops)[op]); 11169 PetscFunctionReturn(PETSC_SUCCESS); 11170 } 11171 11172 /*@ 11173 MatHasOperation - Determines whether the given matrix supports the particular operation. 11174 11175 Not Collective 11176 11177 Input Parameters: 11178 + mat - the matrix 11179 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11180 11181 Output Parameter: 11182 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11183 11184 Level: advanced 11185 11186 Note: 11187 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11188 11189 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11190 @*/ 11191 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11192 { 11193 PetscFunctionBegin; 11194 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11195 PetscAssertPointer(has, 3); 11196 if (mat->ops->hasoperation) { 11197 PetscUseTypeMethod(mat, hasoperation, op, has); 11198 } else { 11199 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11200 else { 11201 *has = PETSC_FALSE; 11202 if (op == MATOP_CREATE_SUBMATRIX) { 11203 PetscMPIInt size; 11204 11205 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11206 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11207 } 11208 } 11209 } 11210 PetscFunctionReturn(PETSC_SUCCESS); 11211 } 11212 11213 /*@ 11214 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11215 11216 Collective 11217 11218 Input Parameter: 11219 . mat - the matrix 11220 11221 Output Parameter: 11222 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11223 11224 Level: beginner 11225 11226 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11227 @*/ 11228 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11229 { 11230 PetscFunctionBegin; 11231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11232 PetscValidType(mat, 1); 11233 PetscAssertPointer(cong, 2); 11234 if (!mat->rmap || !mat->cmap) { 11235 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11236 PetscFunctionReturn(PETSC_SUCCESS); 11237 } 11238 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11239 PetscCall(PetscLayoutSetUp(mat->rmap)); 11240 PetscCall(PetscLayoutSetUp(mat->cmap)); 11241 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11242 if (*cong) mat->congruentlayouts = 1; 11243 else mat->congruentlayouts = 0; 11244 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11245 PetscFunctionReturn(PETSC_SUCCESS); 11246 } 11247 11248 PetscErrorCode MatSetInf(Mat A) 11249 { 11250 PetscFunctionBegin; 11251 PetscUseTypeMethod(A, setinf); 11252 PetscFunctionReturn(PETSC_SUCCESS); 11253 } 11254 11255 /*@ 11256 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 11257 and possibly removes small values from the graph structure. 11258 11259 Collective 11260 11261 Input Parameters: 11262 + A - the matrix 11263 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11264 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11265 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11266 . num_idx - size of 'index' array 11267 - index - array of block indices to use for graph strength of connection weight 11268 11269 Output Parameter: 11270 . graph - the resulting graph 11271 11272 Level: advanced 11273 11274 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11275 @*/ 11276 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11277 { 11278 PetscFunctionBegin; 11279 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11280 PetscValidType(A, 1); 11281 PetscValidLogicalCollectiveBool(A, scale, 3); 11282 PetscAssertPointer(graph, 7); 11283 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11284 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11285 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11286 PetscFunctionReturn(PETSC_SUCCESS); 11287 } 11288 11289 /*@ 11290 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11291 meaning the same memory is used for the matrix, and no new memory is allocated. 11292 11293 Collective 11294 11295 Input Parameters: 11296 + A - the matrix 11297 - 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 11298 11299 Level: intermediate 11300 11301 Developer Note: 11302 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11303 of the arrays in the data structure are unneeded. 11304 11305 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11306 @*/ 11307 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11308 { 11309 PetscFunctionBegin; 11310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11311 PetscUseTypeMethod(A, eliminatezeros, keep); 11312 PetscFunctionReturn(PETSC_SUCCESS); 11313 } 11314