1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 The calling sequence is 586 .vb 587 MatGetRow(matrix,row,ncols,cols,values,ierr) 588 Mat matrix (input) 589 PetscInt row (input) 590 PetscInt ncols (output) 591 PetscInt cols(maxcols) (output) 592 PetscScalar values(maxcols) output 593 .ve 594 where maxcols >= maximum nonzeros in any row of the matrix. 595 596 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 597 @*/ 598 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 599 { 600 PetscInt incols; 601 602 PetscFunctionBegin; 603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 604 PetscValidType(mat, 1); 605 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 607 MatCheckPreallocated(mat, 1); 608 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 609 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 610 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 611 if (ncols) *ncols = incols; 612 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 613 PetscFunctionReturn(PETSC_SUCCESS); 614 } 615 616 /*@ 617 MatConjugate - replaces the matrix values with their complex conjugates 618 619 Logically Collective 620 621 Input Parameter: 622 . mat - the matrix 623 624 Level: advanced 625 626 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 627 @*/ 628 PetscErrorCode MatConjugate(Mat mat) 629 { 630 PetscFunctionBegin; 631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 632 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 633 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 634 PetscUseTypeMethod(mat, conjugate); 635 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 636 } 637 PetscFunctionReturn(PETSC_SUCCESS); 638 } 639 640 /*@C 641 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 642 643 Not Collective 644 645 Input Parameters: 646 + mat - the matrix 647 . row - the row to get 648 . ncols - the number of nonzeros 649 . cols - the columns of the nonzeros 650 - vals - if nonzero the column values 651 652 Level: advanced 653 654 Notes: 655 This routine should be called after you have finished examining the entries. 656 657 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 658 us of the array after it has been restored. If you pass `NULL`, it will 659 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 660 661 Fortran Note: 662 `MatRestoreRow()` MUST be called after `MatGetRow()` 663 before another call to `MatGetRow()` can be made. 664 665 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 666 @*/ 667 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 668 { 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 671 if (ncols) PetscAssertPointer(ncols, 3); 672 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 673 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 674 if (ncols) *ncols = 0; 675 if (cols) *cols = NULL; 676 if (vals) *vals = NULL; 677 PetscFunctionReturn(PETSC_SUCCESS); 678 } 679 680 /*@ 681 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 682 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 693 694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 PetscTryTypeMethod(mat, getrowuppertriangular); 705 PetscFunctionReturn(PETSC_SUCCESS); 706 } 707 708 /*@ 709 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 710 711 Not Collective 712 713 Input Parameter: 714 . mat - the matrix 715 716 Level: advanced 717 718 Note: 719 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 720 721 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 722 @*/ 723 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 724 { 725 PetscFunctionBegin; 726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 727 PetscValidType(mat, 1); 728 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 729 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 730 MatCheckPreallocated(mat, 1); 731 PetscTryTypeMethod(mat, restorerowuppertriangular); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@ 736 MatSetOptionsPrefix - Sets the prefix used for searching for all 737 `Mat` options in the database. 738 739 Logically Collective 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names 744 745 Level: advanced 746 747 Notes: 748 A hyphen (-) must NOT be given at the beginning of the prefix name. 749 The first character of all runtime options is AUTOMATICALLY the hyphen. 750 751 This is NOT used for options for the factorization of the matrix. Normally the 752 prefix is automatically passed in from the PC calling the factorization. To set 753 it directly use `MatSetOptionsPrefixFactor()` 754 755 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 756 @*/ 757 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 758 { 759 PetscFunctionBegin; 760 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 761 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 762 PetscFunctionReturn(PETSC_SUCCESS); 763 } 764 765 /*@ 766 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 767 for matrices created with `MatGetFactor()` 768 769 Logically Collective 770 771 Input Parameters: 772 + A - the matrix 773 - prefix - the prefix to prepend to all option names for the factored matrix 774 775 Level: developer 776 777 Notes: 778 A hyphen (-) must NOT be given at the beginning of the prefix name. 779 The first character of all runtime options is AUTOMATICALLY the hyphen. 780 781 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 782 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 783 784 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 785 @*/ 786 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 787 { 788 PetscFunctionBegin; 789 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 790 if (prefix) { 791 PetscAssertPointer(prefix, 2); 792 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 793 if (prefix != A->factorprefix) { 794 PetscCall(PetscFree(A->factorprefix)); 795 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 796 } 797 } else PetscCall(PetscFree(A->factorprefix)); 798 PetscFunctionReturn(PETSC_SUCCESS); 799 } 800 801 /*@ 802 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 803 for matrices created with `MatGetFactor()` 804 805 Logically Collective 806 807 Input Parameters: 808 + A - the matrix 809 - prefix - the prefix to prepend to all option names for the factored matrix 810 811 Level: developer 812 813 Notes: 814 A hyphen (-) must NOT be given at the beginning of the prefix name. 815 The first character of all runtime options is AUTOMATICALLY the hyphen. 816 817 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 818 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 819 820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 821 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 822 `MatSetOptionsPrefix()` 823 @*/ 824 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 825 { 826 size_t len1, len2, new_len; 827 828 PetscFunctionBegin; 829 PetscValidHeader(A, 1); 830 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 831 if (!A->factorprefix) { 832 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 833 PetscFunctionReturn(PETSC_SUCCESS); 834 } 835 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 836 837 PetscCall(PetscStrlen(A->factorprefix, &len1)); 838 PetscCall(PetscStrlen(prefix, &len2)); 839 new_len = len1 + len2 + 1; 840 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 841 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@ 846 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 847 matrix options in the database. 848 849 Logically Collective 850 851 Input Parameters: 852 + A - the matrix 853 - prefix - the prefix to prepend to all option names 854 855 Level: advanced 856 857 Note: 858 A hyphen (-) must NOT be given at the beginning of the prefix name. 859 The first character of all runtime options is AUTOMATICALLY the hyphen. 860 861 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 862 @*/ 863 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 867 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 868 PetscFunctionReturn(PETSC_SUCCESS); 869 } 870 871 /*@ 872 MatGetOptionsPrefix - Gets the prefix used for searching for all 873 matrix options in the database. 874 875 Not Collective 876 877 Input Parameter: 878 . A - the matrix 879 880 Output Parameter: 881 . prefix - pointer to the prefix string used 882 883 Level: advanced 884 885 Fortran Note: 886 The user should pass in a string `prefix` of 887 sufficient length to hold the prefix. 888 889 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 890 @*/ 891 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 892 { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 895 PetscAssertPointer(prefix, 2); 896 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 897 PetscFunctionReturn(PETSC_SUCCESS); 898 } 899 900 /*@ 901 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 902 903 Not Collective 904 905 Input Parameter: 906 . A - the matrix 907 908 Output Parameter: 909 . state - the object state 910 911 Level: advanced 912 913 Note: 914 Object state is an integer which gets increased every time 915 the object is changed. By saving and later querying the object state 916 one can determine whether information about the object is still current. 917 918 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 919 920 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 921 @*/ 922 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 PetscAssertPointer(state, 2); 927 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 928 PetscFunctionReturn(PETSC_SUCCESS); 929 } 930 931 /*@ 932 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 933 934 Collective 935 936 Input Parameter: 937 . A - the matrix 938 939 Level: beginner 940 941 Notes: 942 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 943 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 944 makes all of the preallocation space available 945 946 Current values in the matrix are lost in this call. 947 948 Currently only supported for `MATAIJ` matrices. 949 950 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 951 @*/ 952 PetscErrorCode MatResetPreallocation(Mat A) 953 { 954 PetscFunctionBegin; 955 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 956 PetscValidType(A, 1); 957 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 958 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 959 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 960 PetscFunctionReturn(PETSC_SUCCESS); 961 } 962 963 /*@ 964 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 965 966 Collective 967 968 Input Parameter: 969 . A - the matrix 970 971 Level: intermediate 972 973 Notes: 974 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 975 976 Currently only supported for `MATAIJ` matrices. 977 978 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 979 @*/ 980 PetscErrorCode MatResetHash(Mat A) 981 { 982 PetscFunctionBegin; 983 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 984 PetscValidType(A, 1); 985 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 986 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 987 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 988 /* These flags are used to determine whether certain setups occur */ 989 A->was_assembled = PETSC_FALSE; 990 A->assembled = PETSC_FALSE; 991 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 992 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 993 PetscFunctionReturn(PETSC_SUCCESS); 994 } 995 996 /*@ 997 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 998 999 Collective 1000 1001 Input Parameter: 1002 . A - the matrix 1003 1004 Level: advanced 1005 1006 Notes: 1007 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1008 setting values in the matrix. 1009 1010 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1011 1012 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1013 @*/ 1014 PetscErrorCode MatSetUp(Mat A) 1015 { 1016 PetscFunctionBegin; 1017 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1018 if (!((PetscObject)A)->type_name) { 1019 PetscMPIInt size; 1020 1021 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1022 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1023 } 1024 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1025 PetscCall(PetscLayoutSetUp(A->rmap)); 1026 PetscCall(PetscLayoutSetUp(A->cmap)); 1027 A->preallocated = PETSC_TRUE; 1028 PetscFunctionReturn(PETSC_SUCCESS); 1029 } 1030 1031 #if defined(PETSC_HAVE_SAWS) 1032 #include <petscviewersaws.h> 1033 #endif 1034 1035 /* 1036 If threadsafety is on extraneous matrices may be printed 1037 1038 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1039 */ 1040 #if !defined(PETSC_HAVE_THREADSAFETY) 1041 static PetscInt insidematview = 0; 1042 #endif 1043 1044 /*@ 1045 MatViewFromOptions - View properties of the matrix based on options set in the options database 1046 1047 Collective 1048 1049 Input Parameters: 1050 + A - the matrix 1051 . obj - optional additional object that provides the options prefix to use 1052 - name - command line option 1053 1054 Options Database Key: 1055 . -mat_view [viewertype]:... - the viewer and its options 1056 1057 Level: intermediate 1058 1059 Note: 1060 .vb 1061 If no value is provided ascii:stdout is used 1062 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1063 for example ascii::ascii_info prints just the information about the object not all details 1064 unless :append is given filename opens in write mode, overwriting what was already there 1065 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1066 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1067 socket[:port] defaults to the standard output port 1068 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1069 .ve 1070 1071 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1072 @*/ 1073 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1074 { 1075 PetscFunctionBegin; 1076 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1077 #if !defined(PETSC_HAVE_THREADSAFETY) 1078 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1079 #endif 1080 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1081 PetscFunctionReturn(PETSC_SUCCESS); 1082 } 1083 1084 /*@ 1085 MatView - display information about a matrix in a variety ways 1086 1087 Collective on viewer 1088 1089 Input Parameters: 1090 + mat - the matrix 1091 - viewer - visualization context 1092 1093 Options Database Keys: 1094 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1095 . -mat_view ::ascii_info_detail - Prints more detailed info 1096 . -mat_view - Prints matrix in ASCII format 1097 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1098 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1099 . -display <name> - Sets display name (default is host) 1100 . -draw_pause <sec> - Sets number of seconds to pause after display 1101 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1102 . -viewer_socket_machine <machine> - - 1103 . -viewer_socket_port <port> - - 1104 . -mat_view binary - save matrix to file in binary format 1105 - -viewer_binary_filename <name> - - 1106 1107 Level: beginner 1108 1109 Notes: 1110 The available visualization contexts include 1111 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1112 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1113 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1114 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1115 1116 The user can open alternative visualization contexts with 1117 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1118 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1119 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1120 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1121 1122 The user can call `PetscViewerPushFormat()` to specify the output 1123 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1124 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1125 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1126 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1127 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1128 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1129 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1130 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1131 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1132 1133 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1134 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1135 1136 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1137 1138 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1139 viewer is used. 1140 1141 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1142 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1143 1144 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1145 and then use the following mouse functions. 1146 .vb 1147 left mouse: zoom in 1148 middle mouse: zoom out 1149 right mouse: continue with the simulation 1150 .ve 1151 1152 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1153 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1154 @*/ 1155 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1156 { 1157 PetscInt rows, cols, rbs, cbs; 1158 PetscBool isascii, isstring, issaws; 1159 PetscViewerFormat format; 1160 PetscMPIInt size; 1161 1162 PetscFunctionBegin; 1163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1164 PetscValidType(mat, 1); 1165 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1166 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1167 1168 PetscCall(PetscViewerGetFormat(viewer, &format)); 1169 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1170 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1171 1172 #if !defined(PETSC_HAVE_THREADSAFETY) 1173 insidematview++; 1174 #endif 1175 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1176 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1177 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1178 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1179 1180 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1181 if (isascii) { 1182 if (!mat->preallocated) { 1183 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1184 #if !defined(PETSC_HAVE_THREADSAFETY) 1185 insidematview--; 1186 #endif 1187 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1188 PetscFunctionReturn(PETSC_SUCCESS); 1189 } 1190 if (!mat->assembled) { 1191 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1192 #if !defined(PETSC_HAVE_THREADSAFETY) 1193 insidematview--; 1194 #endif 1195 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1196 PetscFunctionReturn(PETSC_SUCCESS); 1197 } 1198 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1199 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1200 MatNullSpace nullsp, transnullsp; 1201 1202 PetscCall(PetscViewerASCIIPushTab(viewer)); 1203 PetscCall(MatGetSize(mat, &rows, &cols)); 1204 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1205 if (rbs != 1 || cbs != 1) { 1206 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : "")); 1207 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1208 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1209 if (mat->factortype) { 1210 MatSolverType solver; 1211 PetscCall(MatFactorGetSolverType(mat, &solver)); 1212 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1213 } 1214 if (mat->ops->getinfo) { 1215 MatInfo info; 1216 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1217 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1218 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1219 } 1220 PetscCall(MatGetNullSpace(mat, &nullsp)); 1221 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1222 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1223 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1224 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1225 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1226 PetscCall(PetscViewerASCIIPushTab(viewer)); 1227 PetscCall(MatProductView(mat, viewer)); 1228 PetscCall(PetscViewerASCIIPopTab(viewer)); 1229 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1230 IS tmp; 1231 1232 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1233 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1234 PetscCall(PetscViewerASCIIPushTab(viewer)); 1235 PetscCall(ISView(tmp, viewer)); 1236 PetscCall(PetscViewerASCIIPopTab(viewer)); 1237 PetscCall(ISDestroy(&tmp)); 1238 } 1239 } 1240 } else if (issaws) { 1241 #if defined(PETSC_HAVE_SAWS) 1242 PetscMPIInt rank; 1243 1244 PetscCall(PetscObjectName((PetscObject)mat)); 1245 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1246 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1247 #endif 1248 } else if (isstring) { 1249 const char *type; 1250 PetscCall(MatGetType(mat, &type)); 1251 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1252 PetscTryTypeMethod(mat, view, viewer); 1253 } 1254 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1255 PetscCall(PetscViewerASCIIPushTab(viewer)); 1256 PetscUseTypeMethod(mat, viewnative, viewer); 1257 PetscCall(PetscViewerASCIIPopTab(viewer)); 1258 } else if (mat->ops->view) { 1259 PetscCall(PetscViewerASCIIPushTab(viewer)); 1260 PetscUseTypeMethod(mat, view, viewer); 1261 PetscCall(PetscViewerASCIIPopTab(viewer)); 1262 } 1263 if (isascii) { 1264 PetscCall(PetscViewerGetFormat(viewer, &format)); 1265 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1266 } 1267 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1268 #if !defined(PETSC_HAVE_THREADSAFETY) 1269 insidematview--; 1270 #endif 1271 PetscFunctionReturn(PETSC_SUCCESS); 1272 } 1273 1274 #if defined(PETSC_USE_DEBUG) 1275 #include <../src/sys/totalview/tv_data_display.h> 1276 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1277 { 1278 TV_add_row("Local rows", "int", &mat->rmap->n); 1279 TV_add_row("Local columns", "int", &mat->cmap->n); 1280 TV_add_row("Global rows", "int", &mat->rmap->N); 1281 TV_add_row("Global columns", "int", &mat->cmap->N); 1282 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1283 return TV_format_OK; 1284 } 1285 #endif 1286 1287 /*@ 1288 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1289 with `MatView()`. The matrix format is determined from the options database. 1290 Generates a parallel MPI matrix if the communicator has more than one 1291 processor. The default matrix type is `MATAIJ`. 1292 1293 Collective 1294 1295 Input Parameters: 1296 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1297 or some related function before a call to `MatLoad()` 1298 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1299 1300 Options Database Key: 1301 . -matload_block_size <bs> - set block size 1302 1303 Level: beginner 1304 1305 Notes: 1306 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1307 `Mat` before calling this routine if you wish to set it from the options database. 1308 1309 `MatLoad()` automatically loads into the options database any options 1310 given in the file filename.info where filename is the name of the file 1311 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1312 file will be ignored if you use the -viewer_binary_skip_info option. 1313 1314 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1315 sets the default matrix type AIJ and sets the local and global sizes. 1316 If type and/or size is already set, then the same are used. 1317 1318 In parallel, each processor can load a subset of rows (or the 1319 entire matrix). This routine is especially useful when a large 1320 matrix is stored on disk and only part of it is desired on each 1321 processor. For example, a parallel solver may access only some of 1322 the rows from each processor. The algorithm used here reads 1323 relatively small blocks of data rather than reading the entire 1324 matrix and then subsetting it. 1325 1326 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1327 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1328 or the sequence like 1329 .vb 1330 `PetscViewer` v; 1331 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1332 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1333 `PetscViewerSetFromOptions`(v); 1334 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1335 `PetscViewerFileSetName`(v,"datafile"); 1336 .ve 1337 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1338 $ -viewer_type {binary, hdf5} 1339 1340 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1341 and src/mat/tutorials/ex10.c with the second approach. 1342 1343 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1344 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1345 Multiple objects, both matrices and vectors, can be stored within the same file. 1346 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1347 1348 Most users should not need to know the details of the binary storage 1349 format, since `MatLoad()` and `MatView()` completely hide these details. 1350 But for anyone who is interested, the standard binary matrix storage 1351 format is 1352 1353 .vb 1354 PetscInt MAT_FILE_CLASSID 1355 PetscInt number of rows 1356 PetscInt number of columns 1357 PetscInt total number of nonzeros 1358 PetscInt *number nonzeros in each row 1359 PetscInt *column indices of all nonzeros (starting index is zero) 1360 PetscScalar *values of all nonzeros 1361 .ve 1362 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1363 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1364 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1365 1366 PETSc automatically does the byte swapping for 1367 machines that store the bytes reversed. Thus if you write your own binary 1368 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1369 and `PetscBinaryWrite()` to see how this may be done. 1370 1371 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1372 Each processor's chunk is loaded independently by its owning MPI process. 1373 Multiple objects, both matrices and vectors, can be stored within the same file. 1374 They are looked up by their PetscObject name. 1375 1376 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1377 by default the same structure and naming of the AIJ arrays and column count 1378 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1379 $ save example.mat A b -v7.3 1380 can be directly read by this routine (see Reference 1 for details). 1381 1382 Depending on your MATLAB version, this format might be a default, 1383 otherwise you can set it as default in Preferences. 1384 1385 Unless -nocompression flag is used to save the file in MATLAB, 1386 PETSc must be configured with ZLIB package. 1387 1388 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1389 1390 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1391 1392 Corresponding `MatView()` is not yet implemented. 1393 1394 The loaded matrix is actually a transpose of the original one in MATLAB, 1395 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1396 With this format, matrix is automatically transposed by PETSc, 1397 unless the matrix is marked as SPD or symmetric 1398 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1399 1400 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1401 1402 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1403 @*/ 1404 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1405 { 1406 PetscBool flg; 1407 1408 PetscFunctionBegin; 1409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1410 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1411 1412 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1413 1414 flg = PETSC_FALSE; 1415 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1416 if (flg) { 1417 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1418 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1419 } 1420 flg = PETSC_FALSE; 1421 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1422 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1423 1424 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1425 PetscUseTypeMethod(mat, load, viewer); 1426 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1427 PetscFunctionReturn(PETSC_SUCCESS); 1428 } 1429 1430 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1431 { 1432 Mat_Redundant *redund = *redundant; 1433 1434 PetscFunctionBegin; 1435 if (redund) { 1436 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1437 PetscCall(ISDestroy(&redund->isrow)); 1438 PetscCall(ISDestroy(&redund->iscol)); 1439 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1440 } else { 1441 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1442 PetscCall(PetscFree(redund->sbuf_j)); 1443 PetscCall(PetscFree(redund->sbuf_a)); 1444 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1445 PetscCall(PetscFree(redund->rbuf_j[i])); 1446 PetscCall(PetscFree(redund->rbuf_a[i])); 1447 } 1448 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1449 } 1450 1451 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1452 PetscCall(PetscFree(redund)); 1453 } 1454 PetscFunctionReturn(PETSC_SUCCESS); 1455 } 1456 1457 /*@ 1458 MatDestroy - Frees space taken by a matrix. 1459 1460 Collective 1461 1462 Input Parameter: 1463 . A - the matrix 1464 1465 Level: beginner 1466 1467 Developer Note: 1468 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1469 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1470 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1471 if changes are needed here. 1472 1473 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1474 @*/ 1475 PetscErrorCode MatDestroy(Mat *A) 1476 { 1477 PetscFunctionBegin; 1478 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1479 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1480 if (--((PetscObject)*A)->refct > 0) { 1481 *A = NULL; 1482 PetscFunctionReturn(PETSC_SUCCESS); 1483 } 1484 1485 /* if memory was published with SAWs then destroy it */ 1486 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1487 PetscTryTypeMethod(*A, destroy); 1488 1489 PetscCall(PetscFree((*A)->factorprefix)); 1490 PetscCall(PetscFree((*A)->defaultvectype)); 1491 PetscCall(PetscFree((*A)->defaultrandtype)); 1492 PetscCall(PetscFree((*A)->bsizes)); 1493 PetscCall(PetscFree((*A)->solvertype)); 1494 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1495 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1496 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1497 PetscCall(MatProductClear(*A)); 1498 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1499 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1500 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1501 PetscCall(MatDestroy(&(*A)->schur)); 1502 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1503 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1504 PetscCall(PetscHeaderDestroy(A)); 1505 PetscFunctionReturn(PETSC_SUCCESS); 1506 } 1507 1508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1509 /*@ 1510 MatSetValues - Inserts or adds a block of values into a matrix. 1511 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1512 MUST be called after all calls to `MatSetValues()` have been completed. 1513 1514 Not Collective 1515 1516 Input Parameters: 1517 + mat - the matrix 1518 . v - a logically two-dimensional array of values 1519 . m - the number of rows 1520 . idxm - the global indices of the rows 1521 . n - the number of columns 1522 . idxn - the global indices of the columns 1523 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1524 1525 Level: beginner 1526 1527 Notes: 1528 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1529 1530 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1531 options cannot be mixed without intervening calls to the assembly 1532 routines. 1533 1534 `MatSetValues()` uses 0-based row and column numbers in Fortran 1535 as well as in C. 1536 1537 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1538 simply ignored. This allows easily inserting element stiffness matrices 1539 with homogeneous Dirichlet boundary conditions that you don't want represented 1540 in the matrix. 1541 1542 Efficiency Alert: 1543 The routine `MatSetValuesBlocked()` may offer much better efficiency 1544 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1545 1546 Fortran Notes: 1547 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1548 .vb 1549 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1550 .ve 1551 1552 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1553 1554 Developer Note: 1555 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1556 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1557 1558 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1559 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1560 @*/ 1561 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1562 { 1563 PetscFunctionBeginHot; 1564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1565 PetscValidType(mat, 1); 1566 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1567 PetscAssertPointer(idxm, 3); 1568 PetscAssertPointer(idxn, 5); 1569 MatCheckPreallocated(mat, 1); 1570 1571 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1572 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1573 1574 if (PetscDefined(USE_DEBUG)) { 1575 PetscInt i, j; 1576 1577 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1578 if (v) { 1579 for (i = 0; i < m; i++) { 1580 for (j = 0; j < n; j++) { 1581 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1582 #if defined(PETSC_USE_COMPLEX) 1583 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1584 #else 1585 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1586 #endif 1587 } 1588 } 1589 } 1590 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1591 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1592 } 1593 1594 if (mat->assembled) { 1595 mat->was_assembled = PETSC_TRUE; 1596 mat->assembled = PETSC_FALSE; 1597 } 1598 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1599 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1600 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1605 /*@ 1606 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1607 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1608 MUST be called after all calls to `MatSetValues()` have been completed. 1609 1610 Not Collective 1611 1612 Input Parameters: 1613 + mat - the matrix 1614 . v - a logically two-dimensional array of values 1615 . ism - the rows to provide 1616 . isn - the columns to provide 1617 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1618 1619 Level: beginner 1620 1621 Notes: 1622 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1623 1624 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1625 options cannot be mixed without intervening calls to the assembly 1626 routines. 1627 1628 `MatSetValues()` uses 0-based row and column numbers in Fortran 1629 as well as in C. 1630 1631 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1632 simply ignored. This allows easily inserting element stiffness matrices 1633 with homogeneous Dirichlet boundary conditions that you don't want represented 1634 in the matrix. 1635 1636 Efficiency Alert: 1637 The routine `MatSetValuesBlocked()` may offer much better efficiency 1638 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1639 1640 This is currently not optimized for any particular `ISType` 1641 1642 Developer Note: 1643 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1644 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1645 1646 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1647 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1648 @*/ 1649 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1650 { 1651 PetscInt m, n; 1652 const PetscInt *rows, *cols; 1653 1654 PetscFunctionBeginHot; 1655 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1656 PetscCall(ISGetIndices(ism, &rows)); 1657 PetscCall(ISGetIndices(isn, &cols)); 1658 PetscCall(ISGetLocalSize(ism, &m)); 1659 PetscCall(ISGetLocalSize(isn, &n)); 1660 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1661 PetscCall(ISRestoreIndices(ism, &rows)); 1662 PetscCall(ISRestoreIndices(isn, &cols)); 1663 PetscFunctionReturn(PETSC_SUCCESS); 1664 } 1665 1666 /*@ 1667 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1668 values into a matrix 1669 1670 Not Collective 1671 1672 Input Parameters: 1673 + mat - the matrix 1674 . row - the (block) row to set 1675 - v - a logically two-dimensional array of values 1676 1677 Level: intermediate 1678 1679 Notes: 1680 The values, `v`, are column-oriented (for the block version) and sorted 1681 1682 All the nonzero values in `row` must be provided 1683 1684 The matrix must have previously had its column indices set, likely by having been assembled. 1685 1686 `row` must belong to this MPI process 1687 1688 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1689 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1690 @*/ 1691 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1692 { 1693 PetscInt globalrow; 1694 1695 PetscFunctionBegin; 1696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1697 PetscValidType(mat, 1); 1698 PetscAssertPointer(v, 3); 1699 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1700 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1701 PetscFunctionReturn(PETSC_SUCCESS); 1702 } 1703 1704 /*@ 1705 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1706 values into a matrix 1707 1708 Not Collective 1709 1710 Input Parameters: 1711 + mat - the matrix 1712 . row - the (block) row to set 1713 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1714 1715 Level: advanced 1716 1717 Notes: 1718 The values, `v`, are column-oriented for the block version. 1719 1720 All the nonzeros in `row` must be provided 1721 1722 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1723 1724 `row` must belong to this process 1725 1726 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1727 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1728 @*/ 1729 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1730 { 1731 PetscFunctionBeginHot; 1732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1733 PetscValidType(mat, 1); 1734 MatCheckPreallocated(mat, 1); 1735 PetscAssertPointer(v, 3); 1736 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1737 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1738 mat->insertmode = INSERT_VALUES; 1739 1740 if (mat->assembled) { 1741 mat->was_assembled = PETSC_TRUE; 1742 mat->assembled = PETSC_FALSE; 1743 } 1744 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1745 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1746 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1747 PetscFunctionReturn(PETSC_SUCCESS); 1748 } 1749 1750 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1751 /*@ 1752 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1753 Using structured grid indexing 1754 1755 Not Collective 1756 1757 Input Parameters: 1758 + mat - the matrix 1759 . m - number of rows being entered 1760 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1761 . n - number of columns being entered 1762 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1763 . v - a logically two-dimensional array of values 1764 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1765 1766 Level: beginner 1767 1768 Notes: 1769 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1770 1771 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1772 options cannot be mixed without intervening calls to the assembly 1773 routines. 1774 1775 The grid coordinates are across the entire grid, not just the local portion 1776 1777 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1778 as well as in C. 1779 1780 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1781 1782 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1783 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1784 1785 The columns and rows in the stencil passed in MUST be contained within the 1786 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1787 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1788 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1789 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1790 1791 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1792 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1793 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1794 `DM_BOUNDARY_PERIODIC` boundary type. 1795 1796 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1797 a single value per point) you can skip filling those indices. 1798 1799 Inspired by the structured grid interface to the HYPRE package 1800 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1801 1802 Efficiency Alert: 1803 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1804 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1805 1806 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1807 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1808 @*/ 1809 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1810 { 1811 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1812 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1813 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1814 1815 PetscFunctionBegin; 1816 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1817 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1818 PetscValidType(mat, 1); 1819 PetscAssertPointer(idxm, 3); 1820 PetscAssertPointer(idxn, 5); 1821 1822 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1823 jdxm = buf; 1824 jdxn = buf + m; 1825 } else { 1826 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1827 jdxm = bufm; 1828 jdxn = bufn; 1829 } 1830 for (i = 0; i < m; i++) { 1831 for (j = 0; j < 3 - sdim; j++) dxm++; 1832 tmp = *dxm++ - starts[0]; 1833 for (j = 0; j < dim - 1; j++) { 1834 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1835 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1836 } 1837 if (mat->stencil.noc) dxm++; 1838 jdxm[i] = tmp; 1839 } 1840 for (i = 0; i < n; i++) { 1841 for (j = 0; j < 3 - sdim; j++) dxn++; 1842 tmp = *dxn++ - starts[0]; 1843 for (j = 0; j < dim - 1; j++) { 1844 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1845 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1846 } 1847 if (mat->stencil.noc) dxn++; 1848 jdxn[i] = tmp; 1849 } 1850 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1851 PetscCall(PetscFree2(bufm, bufn)); 1852 PetscFunctionReturn(PETSC_SUCCESS); 1853 } 1854 1855 /*@ 1856 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1857 Using structured grid indexing 1858 1859 Not Collective 1860 1861 Input Parameters: 1862 + mat - the matrix 1863 . m - number of rows being entered 1864 . idxm - grid coordinates for matrix rows being entered 1865 . n - number of columns being entered 1866 . idxn - grid coordinates for matrix columns being entered 1867 . v - a logically two-dimensional array of values 1868 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1869 1870 Level: beginner 1871 1872 Notes: 1873 By default the values, `v`, are row-oriented and unsorted. 1874 See `MatSetOption()` for other options. 1875 1876 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1877 options cannot be mixed without intervening calls to the assembly 1878 routines. 1879 1880 The grid coordinates are across the entire grid, not just the local portion 1881 1882 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1883 as well as in C. 1884 1885 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1886 1887 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1888 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1889 1890 The columns and rows in the stencil passed in MUST be contained within the 1891 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1892 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1893 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1894 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1895 1896 Negative indices may be passed in idxm and idxn, these rows and columns are 1897 simply ignored. This allows easily inserting element stiffness matrices 1898 with homogeneous Dirichlet boundary conditions that you don't want represented 1899 in the matrix. 1900 1901 Inspired by the structured grid interface to the HYPRE package 1902 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1903 1904 Fortran Note: 1905 `idxm` and `idxn` should be declared as 1906 $ MatStencil idxm(4,m),idxn(4,n) 1907 and the values inserted using 1908 .vb 1909 idxm(MatStencil_i,1) = i 1910 idxm(MatStencil_j,1) = j 1911 idxm(MatStencil_k,1) = k 1912 etc 1913 .ve 1914 1915 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1916 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1917 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1918 @*/ 1919 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1920 { 1921 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1922 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1923 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1924 1925 PetscFunctionBegin; 1926 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1928 PetscValidType(mat, 1); 1929 PetscAssertPointer(idxm, 3); 1930 PetscAssertPointer(idxn, 5); 1931 PetscAssertPointer(v, 6); 1932 1933 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1934 jdxm = buf; 1935 jdxn = buf + m; 1936 } else { 1937 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1938 jdxm = bufm; 1939 jdxn = bufn; 1940 } 1941 for (i = 0; i < m; i++) { 1942 for (j = 0; j < 3 - sdim; j++) dxm++; 1943 tmp = *dxm++ - starts[0]; 1944 for (j = 0; j < sdim - 1; j++) { 1945 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1946 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1947 } 1948 dxm++; 1949 jdxm[i] = tmp; 1950 } 1951 for (i = 0; i < n; i++) { 1952 for (j = 0; j < 3 - sdim; j++) dxn++; 1953 tmp = *dxn++ - starts[0]; 1954 for (j = 0; j < sdim - 1; j++) { 1955 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1956 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1957 } 1958 dxn++; 1959 jdxn[i] = tmp; 1960 } 1961 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1962 PetscCall(PetscFree2(bufm, bufn)); 1963 PetscFunctionReturn(PETSC_SUCCESS); 1964 } 1965 1966 /*@ 1967 MatSetStencil - Sets the grid information for setting values into a matrix via 1968 `MatSetValuesStencil()` 1969 1970 Not Collective 1971 1972 Input Parameters: 1973 + mat - the matrix 1974 . dim - dimension of the grid 1, 2, or 3 1975 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1976 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1977 - dof - number of degrees of freedom per node 1978 1979 Level: beginner 1980 1981 Notes: 1982 Inspired by the structured grid interface to the HYPRE package 1983 (www.llnl.gov/CASC/hyper) 1984 1985 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1986 user. 1987 1988 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1989 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1990 @*/ 1991 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1992 { 1993 PetscFunctionBegin; 1994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1995 PetscAssertPointer(dims, 3); 1996 PetscAssertPointer(starts, 4); 1997 1998 mat->stencil.dim = dim + (dof > 1); 1999 for (PetscInt i = 0; i < dim; i++) { 2000 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2001 mat->stencil.starts[i] = starts[dim - i - 1]; 2002 } 2003 mat->stencil.dims[dim] = dof; 2004 mat->stencil.starts[dim] = 0; 2005 mat->stencil.noc = (PetscBool)(dof == 1); 2006 PetscFunctionReturn(PETSC_SUCCESS); 2007 } 2008 2009 /*@ 2010 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2011 2012 Not Collective 2013 2014 Input Parameters: 2015 + mat - the matrix 2016 . v - a logically two-dimensional array of values 2017 . m - the number of block rows 2018 . idxm - the global block indices 2019 . n - the number of block columns 2020 . idxn - the global block indices 2021 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2022 2023 Level: intermediate 2024 2025 Notes: 2026 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2027 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2028 2029 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2030 NOT the total number of rows/columns; for example, if the block size is 2 and 2031 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2032 The values in `idxm` would be 1 2; that is the first index for each block divided by 2033 the block size. 2034 2035 You must call `MatSetBlockSize()` when constructing this matrix (before 2036 preallocating it). 2037 2038 By default the values, `v`, are row-oriented, so the layout of 2039 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2040 2041 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2042 options cannot be mixed without intervening calls to the assembly 2043 routines. 2044 2045 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2046 as well as in C. 2047 2048 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2049 simply ignored. This allows easily inserting element stiffness matrices 2050 with homogeneous Dirichlet boundary conditions that you don't want represented 2051 in the matrix. 2052 2053 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2054 internal searching must be done to determine where to place the 2055 data in the matrix storage space. By instead inserting blocks of 2056 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2057 reduced. 2058 2059 Example: 2060 .vb 2061 Suppose m=n=2 and block size(bs) = 2 The array is 2062 2063 1 2 | 3 4 2064 5 6 | 7 8 2065 - - - | - - - 2066 9 10 | 11 12 2067 13 14 | 15 16 2068 2069 v[] should be passed in like 2070 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2071 2072 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2073 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2074 .ve 2075 2076 Fortran Notes: 2077 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2078 .vb 2079 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2080 .ve 2081 2082 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2083 2084 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2085 @*/ 2086 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2087 { 2088 PetscFunctionBeginHot; 2089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2090 PetscValidType(mat, 1); 2091 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2092 PetscAssertPointer(idxm, 3); 2093 PetscAssertPointer(idxn, 5); 2094 MatCheckPreallocated(mat, 1); 2095 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2096 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2097 if (PetscDefined(USE_DEBUG)) { 2098 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2099 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2100 } 2101 if (PetscDefined(USE_DEBUG)) { 2102 PetscInt rbs, cbs, M, N, i; 2103 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2104 PetscCall(MatGetSize(mat, &M, &N)); 2105 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); 2106 for (i = 0; i < n; i++) 2107 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); 2108 } 2109 if (mat->assembled) { 2110 mat->was_assembled = PETSC_TRUE; 2111 mat->assembled = PETSC_FALSE; 2112 } 2113 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2114 if (mat->ops->setvaluesblocked) { 2115 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2116 } else { 2117 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2118 PetscInt i, j, bs, cbs; 2119 2120 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2121 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2122 iidxm = buf; 2123 iidxn = buf + m * bs; 2124 } else { 2125 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2126 iidxm = bufr; 2127 iidxn = bufc; 2128 } 2129 for (i = 0; i < m; i++) { 2130 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2131 } 2132 if (m != n || bs != cbs || idxm != idxn) { 2133 for (i = 0; i < n; i++) { 2134 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2135 } 2136 } else iidxn = iidxm; 2137 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2138 PetscCall(PetscFree2(bufr, bufc)); 2139 } 2140 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@ 2145 MatGetValues - Gets a block of local values from a matrix. 2146 2147 Not Collective; can only return values that are owned by the give process 2148 2149 Input Parameters: 2150 + mat - the matrix 2151 . v - a logically two-dimensional array for storing the values 2152 . m - the number of rows 2153 . idxm - the global indices of the rows 2154 . n - the number of columns 2155 - idxn - the global indices of the columns 2156 2157 Level: advanced 2158 2159 Notes: 2160 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2161 The values, `v`, are then returned in a row-oriented format, 2162 analogous to that used by default in `MatSetValues()`. 2163 2164 `MatGetValues()` uses 0-based row and column numbers in 2165 Fortran as well as in C. 2166 2167 `MatGetValues()` requires that the matrix has been assembled 2168 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2169 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2170 without intermediate matrix assembly. 2171 2172 Negative row or column indices will be ignored and those locations in `v` will be 2173 left unchanged. 2174 2175 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2176 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2177 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2178 2179 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2180 @*/ 2181 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2182 { 2183 PetscFunctionBegin; 2184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2185 PetscValidType(mat, 1); 2186 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2187 PetscAssertPointer(idxm, 3); 2188 PetscAssertPointer(idxn, 5); 2189 PetscAssertPointer(v, 6); 2190 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2191 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2192 MatCheckPreallocated(mat, 1); 2193 2194 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2195 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2196 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2197 PetscFunctionReturn(PETSC_SUCCESS); 2198 } 2199 2200 /*@ 2201 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2202 defined previously by `MatSetLocalToGlobalMapping()` 2203 2204 Not Collective 2205 2206 Input Parameters: 2207 + mat - the matrix 2208 . nrow - number of rows 2209 . irow - the row local indices 2210 . ncol - number of columns 2211 - icol - the column local indices 2212 2213 Output Parameter: 2214 . y - a logically two-dimensional array of values 2215 2216 Level: advanced 2217 2218 Notes: 2219 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2220 2221 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, 2222 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2223 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2224 with `MatSetLocalToGlobalMapping()`. 2225 2226 Developer Note: 2227 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2228 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2229 2230 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2231 `MatSetValuesLocal()`, `MatGetValues()` 2232 @*/ 2233 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2234 { 2235 PetscFunctionBeginHot; 2236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2237 PetscValidType(mat, 1); 2238 MatCheckPreallocated(mat, 1); 2239 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2240 PetscAssertPointer(irow, 3); 2241 PetscAssertPointer(icol, 5); 2242 if (PetscDefined(USE_DEBUG)) { 2243 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2244 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2245 } 2246 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2247 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2248 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2249 else { 2250 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2251 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2252 irowm = buf; 2253 icolm = buf + nrow; 2254 } else { 2255 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2256 irowm = bufr; 2257 icolm = bufc; 2258 } 2259 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2260 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2261 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2262 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2263 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2264 PetscCall(PetscFree2(bufr, bufc)); 2265 } 2266 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2267 PetscFunctionReturn(PETSC_SUCCESS); 2268 } 2269 2270 /*@ 2271 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2272 the same size. Currently, this can only be called once and creates the given matrix. 2273 2274 Not Collective 2275 2276 Input Parameters: 2277 + mat - the matrix 2278 . nb - the number of blocks 2279 . bs - the number of rows (and columns) in each block 2280 . rows - a concatenation of the rows for each block 2281 - v - a concatenation of logically two-dimensional arrays of values 2282 2283 Level: advanced 2284 2285 Notes: 2286 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2287 2288 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2289 2290 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2291 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2292 @*/ 2293 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2294 { 2295 PetscFunctionBegin; 2296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2297 PetscValidType(mat, 1); 2298 PetscAssertPointer(rows, 4); 2299 PetscAssertPointer(v, 5); 2300 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2301 2302 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2303 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2304 else { 2305 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2306 } 2307 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2308 PetscFunctionReturn(PETSC_SUCCESS); 2309 } 2310 2311 /*@ 2312 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2313 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2314 using a local (per-processor) numbering. 2315 2316 Not Collective 2317 2318 Input Parameters: 2319 + x - the matrix 2320 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2321 - cmapping - column mapping 2322 2323 Level: intermediate 2324 2325 Note: 2326 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2327 2328 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2329 @*/ 2330 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2331 { 2332 PetscFunctionBegin; 2333 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2334 PetscValidType(x, 1); 2335 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2336 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2337 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2338 else { 2339 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2340 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2341 } 2342 PetscFunctionReturn(PETSC_SUCCESS); 2343 } 2344 2345 /*@ 2346 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2347 2348 Not Collective 2349 2350 Input Parameter: 2351 . A - the matrix 2352 2353 Output Parameters: 2354 + rmapping - row mapping 2355 - cmapping - column mapping 2356 2357 Level: advanced 2358 2359 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2360 @*/ 2361 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2362 { 2363 PetscFunctionBegin; 2364 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2365 PetscValidType(A, 1); 2366 if (rmapping) { 2367 PetscAssertPointer(rmapping, 2); 2368 *rmapping = A->rmap->mapping; 2369 } 2370 if (cmapping) { 2371 PetscAssertPointer(cmapping, 3); 2372 *cmapping = A->cmap->mapping; 2373 } 2374 PetscFunctionReturn(PETSC_SUCCESS); 2375 } 2376 2377 /*@ 2378 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2379 2380 Logically Collective 2381 2382 Input Parameters: 2383 + A - the matrix 2384 . rmap - row layout 2385 - cmap - column layout 2386 2387 Level: advanced 2388 2389 Note: 2390 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2391 2392 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2393 @*/ 2394 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2395 { 2396 PetscFunctionBegin; 2397 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2398 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2399 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2400 PetscFunctionReturn(PETSC_SUCCESS); 2401 } 2402 2403 /*@ 2404 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2405 2406 Not Collective 2407 2408 Input Parameter: 2409 . A - the matrix 2410 2411 Output Parameters: 2412 + rmap - row layout 2413 - cmap - column layout 2414 2415 Level: advanced 2416 2417 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2418 @*/ 2419 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2420 { 2421 PetscFunctionBegin; 2422 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2423 PetscValidType(A, 1); 2424 if (rmap) { 2425 PetscAssertPointer(rmap, 2); 2426 *rmap = A->rmap; 2427 } 2428 if (cmap) { 2429 PetscAssertPointer(cmap, 3); 2430 *cmap = A->cmap; 2431 } 2432 PetscFunctionReturn(PETSC_SUCCESS); 2433 } 2434 2435 /*@ 2436 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2437 using a local numbering of the rows and columns. 2438 2439 Not Collective 2440 2441 Input Parameters: 2442 + mat - the matrix 2443 . nrow - number of rows 2444 . irow - the row local indices 2445 . ncol - number of columns 2446 . icol - the column local indices 2447 . y - a logically two-dimensional array of values 2448 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2449 2450 Level: intermediate 2451 2452 Notes: 2453 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2454 2455 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2456 options cannot be mixed without intervening calls to the assembly 2457 routines. 2458 2459 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2460 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2461 2462 Fortran Notes: 2463 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2464 .vb 2465 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2466 .ve 2467 2468 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2469 2470 Developer Note: 2471 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2472 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2473 2474 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2475 `MatGetValuesLocal()` 2476 @*/ 2477 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2478 { 2479 PetscFunctionBeginHot; 2480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2481 PetscValidType(mat, 1); 2482 MatCheckPreallocated(mat, 1); 2483 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2484 PetscAssertPointer(irow, 3); 2485 PetscAssertPointer(icol, 5); 2486 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2487 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2488 if (PetscDefined(USE_DEBUG)) { 2489 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2490 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2491 } 2492 2493 if (mat->assembled) { 2494 mat->was_assembled = PETSC_TRUE; 2495 mat->assembled = PETSC_FALSE; 2496 } 2497 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2498 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2499 else { 2500 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2501 const PetscInt *irowm, *icolm; 2502 2503 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2504 bufr = buf; 2505 bufc = buf + nrow; 2506 irowm = bufr; 2507 icolm = bufc; 2508 } else { 2509 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2510 irowm = bufr; 2511 icolm = bufc; 2512 } 2513 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2514 else irowm = irow; 2515 if (mat->cmap->mapping) { 2516 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2517 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2518 } else icolm = irowm; 2519 } else icolm = icol; 2520 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2521 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2522 } 2523 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2524 PetscFunctionReturn(PETSC_SUCCESS); 2525 } 2526 2527 /*@ 2528 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2529 using a local ordering of the nodes a block at a time. 2530 2531 Not Collective 2532 2533 Input Parameters: 2534 + mat - the matrix 2535 . nrow - number of rows 2536 . irow - the row local indices 2537 . ncol - number of columns 2538 . icol - the column local indices 2539 . y - a logically two-dimensional array of values 2540 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2541 2542 Level: intermediate 2543 2544 Notes: 2545 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2546 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2547 2548 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2549 options cannot be mixed without intervening calls to the assembly 2550 routines. 2551 2552 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2553 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2554 2555 Fortran Notes: 2556 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2557 .vb 2558 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2559 .ve 2560 2561 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2562 2563 Developer Note: 2564 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2565 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2566 2567 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2568 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2569 @*/ 2570 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2571 { 2572 PetscFunctionBeginHot; 2573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2574 PetscValidType(mat, 1); 2575 MatCheckPreallocated(mat, 1); 2576 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2577 PetscAssertPointer(irow, 3); 2578 PetscAssertPointer(icol, 5); 2579 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2580 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2581 if (PetscDefined(USE_DEBUG)) { 2582 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2583 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); 2584 } 2585 2586 if (mat->assembled) { 2587 mat->was_assembled = PETSC_TRUE; 2588 mat->assembled = PETSC_FALSE; 2589 } 2590 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2591 PetscInt irbs, rbs; 2592 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2593 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2594 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2595 } 2596 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2597 PetscInt icbs, cbs; 2598 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2599 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2600 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2601 } 2602 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2603 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2604 else { 2605 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2606 const PetscInt *irowm, *icolm; 2607 2608 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2609 bufr = buf; 2610 bufc = buf + nrow; 2611 irowm = bufr; 2612 icolm = bufc; 2613 } else { 2614 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2615 irowm = bufr; 2616 icolm = bufc; 2617 } 2618 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2619 else irowm = irow; 2620 if (mat->cmap->mapping) { 2621 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2622 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2623 } else icolm = irowm; 2624 } else icolm = icol; 2625 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2626 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2627 } 2628 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2629 PetscFunctionReturn(PETSC_SUCCESS); 2630 } 2631 2632 /*@ 2633 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2634 2635 Collective 2636 2637 Input Parameters: 2638 + mat - the matrix 2639 - x - the vector to be multiplied 2640 2641 Output Parameter: 2642 . y - the result 2643 2644 Level: developer 2645 2646 Note: 2647 The vectors `x` and `y` cannot be the same. I.e., one cannot 2648 call `MatMultDiagonalBlock`(A,y,y). 2649 2650 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2651 @*/ 2652 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2653 { 2654 PetscFunctionBegin; 2655 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2656 PetscValidType(mat, 1); 2657 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2658 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2659 2660 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2661 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2662 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2663 MatCheckPreallocated(mat, 1); 2664 2665 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2666 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2667 PetscFunctionReturn(PETSC_SUCCESS); 2668 } 2669 2670 /*@ 2671 MatMult - Computes the matrix-vector product, $y = Ax$. 2672 2673 Neighbor-wise Collective 2674 2675 Input Parameters: 2676 + mat - the matrix 2677 - x - the vector to be multiplied 2678 2679 Output Parameter: 2680 . y - the result 2681 2682 Level: beginner 2683 2684 Note: 2685 The vectors `x` and `y` cannot be the same. I.e., one cannot 2686 call `MatMult`(A,y,y). 2687 2688 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2689 @*/ 2690 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2691 { 2692 PetscFunctionBegin; 2693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2694 PetscValidType(mat, 1); 2695 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2696 VecCheckAssembled(x); 2697 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2698 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2699 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2700 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2701 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); 2702 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); 2703 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); 2704 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); 2705 PetscCall(VecSetErrorIfLocked(y, 3)); 2706 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2707 MatCheckPreallocated(mat, 1); 2708 2709 PetscCall(VecLockReadPush(x)); 2710 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2711 PetscUseTypeMethod(mat, mult, x, y); 2712 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2713 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2714 PetscCall(VecLockReadPop(x)); 2715 PetscFunctionReturn(PETSC_SUCCESS); 2716 } 2717 2718 /*@ 2719 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2720 2721 Neighbor-wise Collective 2722 2723 Input Parameters: 2724 + mat - the matrix 2725 - x - the vector to be multiplied 2726 2727 Output Parameter: 2728 . y - the result 2729 2730 Level: beginner 2731 2732 Notes: 2733 The vectors `x` and `y` cannot be the same. I.e., one cannot 2734 call `MatMultTranspose`(A,y,y). 2735 2736 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2737 use `MatMultHermitianTranspose()` 2738 2739 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2740 @*/ 2741 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2742 { 2743 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2744 2745 PetscFunctionBegin; 2746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2747 PetscValidType(mat, 1); 2748 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2749 VecCheckAssembled(x); 2750 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2751 2752 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2753 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2754 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2755 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); 2756 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); 2757 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); 2758 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); 2759 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2760 MatCheckPreallocated(mat, 1); 2761 2762 if (!mat->ops->multtranspose) { 2763 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2764 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); 2765 } else op = mat->ops->multtranspose; 2766 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2767 PetscCall(VecLockReadPush(x)); 2768 PetscCall((*op)(mat, x, y)); 2769 PetscCall(VecLockReadPop(x)); 2770 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2771 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2772 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2773 PetscFunctionReturn(PETSC_SUCCESS); 2774 } 2775 2776 /*@ 2777 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2778 2779 Neighbor-wise Collective 2780 2781 Input Parameters: 2782 + mat - the matrix 2783 - x - the vector to be multiplied 2784 2785 Output Parameter: 2786 . y - the result 2787 2788 Level: beginner 2789 2790 Notes: 2791 The vectors `x` and `y` cannot be the same. I.e., one cannot 2792 call `MatMultHermitianTranspose`(A,y,y). 2793 2794 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2795 2796 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2797 2798 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2799 @*/ 2800 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2801 { 2802 PetscFunctionBegin; 2803 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2804 PetscValidType(mat, 1); 2805 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2806 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2807 2808 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2809 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2810 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2811 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); 2812 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); 2813 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); 2814 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); 2815 MatCheckPreallocated(mat, 1); 2816 2817 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2818 #if defined(PETSC_USE_COMPLEX) 2819 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2820 PetscCall(VecLockReadPush(x)); 2821 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2822 else PetscUseTypeMethod(mat, mult, x, y); 2823 PetscCall(VecLockReadPop(x)); 2824 } else { 2825 Vec w; 2826 PetscCall(VecDuplicate(x, &w)); 2827 PetscCall(VecCopy(x, w)); 2828 PetscCall(VecConjugate(w)); 2829 PetscCall(MatMultTranspose(mat, w, y)); 2830 PetscCall(VecDestroy(&w)); 2831 PetscCall(VecConjugate(y)); 2832 } 2833 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2834 #else 2835 PetscCall(MatMultTranspose(mat, x, y)); 2836 #endif 2837 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2838 PetscFunctionReturn(PETSC_SUCCESS); 2839 } 2840 2841 /*@ 2842 MatMultAdd - Computes $v3 = v2 + A * v1$. 2843 2844 Neighbor-wise Collective 2845 2846 Input Parameters: 2847 + mat - the matrix 2848 . v1 - the vector to be multiplied by `mat` 2849 - v2 - the vector to be added to the result 2850 2851 Output Parameter: 2852 . v3 - the result 2853 2854 Level: beginner 2855 2856 Note: 2857 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2858 call `MatMultAdd`(A,v1,v2,v1). 2859 2860 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2861 @*/ 2862 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2863 { 2864 PetscFunctionBegin; 2865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2866 PetscValidType(mat, 1); 2867 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2868 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2869 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2870 2871 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2872 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2873 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); 2874 /* 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); 2875 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); */ 2876 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); 2877 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); 2878 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2879 MatCheckPreallocated(mat, 1); 2880 2881 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2882 PetscCall(VecLockReadPush(v1)); 2883 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2884 PetscCall(VecLockReadPop(v1)); 2885 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2886 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@ 2891 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2892 2893 Neighbor-wise Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 . v1 - the vector to be multiplied by the transpose of the matrix 2898 - v2 - the vector to be added to the result 2899 2900 Output Parameter: 2901 . v3 - the result 2902 2903 Level: beginner 2904 2905 Note: 2906 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2907 call `MatMultTransposeAdd`(A,v1,v2,v1). 2908 2909 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2910 @*/ 2911 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2912 { 2913 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2914 2915 PetscFunctionBegin; 2916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2917 PetscValidType(mat, 1); 2918 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2919 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2920 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2921 2922 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2923 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2924 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); 2925 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); 2926 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); 2927 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2928 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2929 MatCheckPreallocated(mat, 1); 2930 2931 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2932 PetscCall(VecLockReadPush(v1)); 2933 PetscCall((*op)(mat, v1, v2, v3)); 2934 PetscCall(VecLockReadPop(v1)); 2935 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2936 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2937 PetscFunctionReturn(PETSC_SUCCESS); 2938 } 2939 2940 /*@ 2941 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2942 2943 Neighbor-wise Collective 2944 2945 Input Parameters: 2946 + mat - the matrix 2947 . v1 - the vector to be multiplied by the Hermitian transpose 2948 - v2 - the vector to be added to the result 2949 2950 Output Parameter: 2951 . v3 - the result 2952 2953 Level: beginner 2954 2955 Note: 2956 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2957 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2958 2959 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2960 @*/ 2961 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2962 { 2963 PetscFunctionBegin; 2964 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2965 PetscValidType(mat, 1); 2966 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2967 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2968 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2969 2970 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2971 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2972 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2973 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); 2974 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); 2975 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); 2976 MatCheckPreallocated(mat, 1); 2977 2978 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2979 PetscCall(VecLockReadPush(v1)); 2980 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2981 else { 2982 Vec w, z; 2983 PetscCall(VecDuplicate(v1, &w)); 2984 PetscCall(VecCopy(v1, w)); 2985 PetscCall(VecConjugate(w)); 2986 PetscCall(VecDuplicate(v3, &z)); 2987 PetscCall(MatMultTranspose(mat, w, z)); 2988 PetscCall(VecDestroy(&w)); 2989 PetscCall(VecConjugate(z)); 2990 if (v2 != v3) { 2991 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2992 } else { 2993 PetscCall(VecAXPY(v3, 1.0, z)); 2994 } 2995 PetscCall(VecDestroy(&z)); 2996 } 2997 PetscCall(VecLockReadPop(v1)); 2998 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2999 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 3000 PetscFunctionReturn(PETSC_SUCCESS); 3001 } 3002 3003 /*@ 3004 MatGetFactorType - gets the type of factorization a matrix is 3005 3006 Not Collective 3007 3008 Input Parameter: 3009 . mat - the matrix 3010 3011 Output Parameter: 3012 . 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` 3013 3014 Level: intermediate 3015 3016 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3017 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3018 @*/ 3019 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3020 { 3021 PetscFunctionBegin; 3022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3023 PetscValidType(mat, 1); 3024 PetscAssertPointer(t, 2); 3025 *t = mat->factortype; 3026 PetscFunctionReturn(PETSC_SUCCESS); 3027 } 3028 3029 /*@ 3030 MatSetFactorType - sets the type of factorization a matrix is 3031 3032 Logically Collective 3033 3034 Input Parameters: 3035 + mat - the matrix 3036 - 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` 3037 3038 Level: intermediate 3039 3040 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3041 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3042 @*/ 3043 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3044 { 3045 PetscFunctionBegin; 3046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3047 PetscValidType(mat, 1); 3048 mat->factortype = t; 3049 PetscFunctionReturn(PETSC_SUCCESS); 3050 } 3051 3052 /*@ 3053 MatGetInfo - Returns information about matrix storage (number of 3054 nonzeros, memory, etc.). 3055 3056 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3057 3058 Input Parameters: 3059 + mat - the matrix 3060 - 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) 3061 3062 Output Parameter: 3063 . info - matrix information context 3064 3065 Options Database Key: 3066 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3067 3068 Level: intermediate 3069 3070 Notes: 3071 The `MatInfo` context contains a variety of matrix data, including 3072 number of nonzeros allocated and used, number of mallocs during 3073 matrix assembly, etc. Additional information for factored matrices 3074 is provided (such as the fill ratio, number of mallocs during 3075 factorization, etc.). 3076 3077 Example: 3078 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3079 data within the `MatInfo` context. For example, 3080 .vb 3081 MatInfo info; 3082 Mat A; 3083 double mal, nz_a, nz_u; 3084 3085 MatGetInfo(A, MAT_LOCAL, &info); 3086 mal = info.mallocs; 3087 nz_a = info.nz_allocated; 3088 .ve 3089 3090 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3091 @*/ 3092 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3093 { 3094 PetscFunctionBegin; 3095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3096 PetscValidType(mat, 1); 3097 PetscAssertPointer(info, 3); 3098 MatCheckPreallocated(mat, 1); 3099 PetscUseTypeMethod(mat, getinfo, flag, info); 3100 PetscFunctionReturn(PETSC_SUCCESS); 3101 } 3102 3103 /* 3104 This is used by external packages where it is not easy to get the info from the actual 3105 matrix factorization. 3106 */ 3107 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3108 { 3109 PetscFunctionBegin; 3110 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3111 PetscFunctionReturn(PETSC_SUCCESS); 3112 } 3113 3114 /*@ 3115 MatLUFactor - Performs in-place LU factorization of matrix. 3116 3117 Collective 3118 3119 Input Parameters: 3120 + mat - the matrix 3121 . row - row permutation 3122 . col - column permutation 3123 - info - options for factorization, includes 3124 .vb 3125 fill - expected fill as ratio of original fill. 3126 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3127 Run with the option -info to determine an optimal value to use 3128 .ve 3129 3130 Level: developer 3131 3132 Notes: 3133 Most users should employ the `KSP` interface for linear solvers 3134 instead of working directly with matrix algebra routines such as this. 3135 See, e.g., `KSPCreate()`. 3136 3137 This changes the state of the matrix to a factored matrix; it cannot be used 3138 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3139 3140 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3141 when not using `KSP`. 3142 3143 Developer Note: 3144 The Fortran interface is not autogenerated as the 3145 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3146 3147 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3148 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3149 @*/ 3150 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3151 { 3152 MatFactorInfo tinfo; 3153 3154 PetscFunctionBegin; 3155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3156 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3157 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3158 if (info) PetscAssertPointer(info, 4); 3159 PetscValidType(mat, 1); 3160 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3161 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3162 MatCheckPreallocated(mat, 1); 3163 if (!info) { 3164 PetscCall(MatFactorInfoInitialize(&tinfo)); 3165 info = &tinfo; 3166 } 3167 3168 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3169 PetscUseTypeMethod(mat, lufactor, row, col, info); 3170 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3171 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3172 PetscFunctionReturn(PETSC_SUCCESS); 3173 } 3174 3175 /*@ 3176 MatILUFactor - Performs in-place ILU factorization of matrix. 3177 3178 Collective 3179 3180 Input Parameters: 3181 + mat - the matrix 3182 . row - row permutation 3183 . col - column permutation 3184 - info - structure containing 3185 .vb 3186 levels - number of levels of fill. 3187 expected fill - as ratio of original fill. 3188 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3189 missing diagonal entries) 3190 .ve 3191 3192 Level: developer 3193 3194 Notes: 3195 Most users should employ the `KSP` interface for linear solvers 3196 instead of working directly with matrix algebra routines such as this. 3197 See, e.g., `KSPCreate()`. 3198 3199 Probably really in-place only when level of fill is zero, otherwise allocates 3200 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3201 when not using `KSP`. 3202 3203 Developer Note: 3204 The Fortran interface is not autogenerated as the 3205 interface definition cannot be generated correctly [due to MatFactorInfo] 3206 3207 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3208 @*/ 3209 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3210 { 3211 PetscFunctionBegin; 3212 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3213 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3214 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3215 PetscAssertPointer(info, 4); 3216 PetscValidType(mat, 1); 3217 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3218 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3219 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3220 MatCheckPreallocated(mat, 1); 3221 3222 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3223 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3224 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3225 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3226 PetscFunctionReturn(PETSC_SUCCESS); 3227 } 3228 3229 /*@ 3230 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3231 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3232 3233 Collective 3234 3235 Input Parameters: 3236 + fact - the factor matrix obtained with `MatGetFactor()` 3237 . mat - the matrix 3238 . row - the row permutation 3239 . col - the column permutation 3240 - info - options for factorization, includes 3241 .vb 3242 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3243 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3244 .ve 3245 3246 Level: developer 3247 3248 Notes: 3249 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3250 3251 Most users should employ the simplified `KSP` interface for linear solvers 3252 instead of working directly with matrix algebra routines such as this. 3253 See, e.g., `KSPCreate()`. 3254 3255 Developer Note: 3256 The Fortran interface is not autogenerated as the 3257 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3258 3259 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3260 @*/ 3261 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3262 { 3263 MatFactorInfo tinfo; 3264 3265 PetscFunctionBegin; 3266 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3268 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3269 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3270 if (info) PetscAssertPointer(info, 5); 3271 PetscValidType(fact, 1); 3272 PetscValidType(mat, 2); 3273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3275 MatCheckPreallocated(mat, 2); 3276 if (!info) { 3277 PetscCall(MatFactorInfoInitialize(&tinfo)); 3278 info = &tinfo; 3279 } 3280 3281 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3282 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3283 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3284 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3285 PetscFunctionReturn(PETSC_SUCCESS); 3286 } 3287 3288 /*@ 3289 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3290 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3291 3292 Collective 3293 3294 Input Parameters: 3295 + fact - the factor matrix obtained with `MatGetFactor()` 3296 . mat - the matrix 3297 - info - options for factorization 3298 3299 Level: developer 3300 3301 Notes: 3302 See `MatLUFactor()` for in-place factorization. See 3303 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3304 3305 Most users should employ the `KSP` interface for linear solvers 3306 instead of working directly with matrix algebra routines such as this. 3307 See, e.g., `KSPCreate()`. 3308 3309 Developer Note: 3310 The Fortran interface is not autogenerated as the 3311 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3312 3313 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3314 @*/ 3315 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3316 { 3317 MatFactorInfo tinfo; 3318 3319 PetscFunctionBegin; 3320 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3321 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3322 PetscValidType(fact, 1); 3323 PetscValidType(mat, 2); 3324 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3325 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, 3326 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3327 3328 MatCheckPreallocated(mat, 2); 3329 if (!info) { 3330 PetscCall(MatFactorInfoInitialize(&tinfo)); 3331 info = &tinfo; 3332 } 3333 3334 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3335 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3336 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3337 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3338 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3339 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3340 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3341 PetscFunctionReturn(PETSC_SUCCESS); 3342 } 3343 3344 /*@ 3345 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3346 symmetric matrix. 3347 3348 Collective 3349 3350 Input Parameters: 3351 + mat - the matrix 3352 . perm - row and column permutations 3353 - info - expected fill as ratio of original fill 3354 3355 Level: developer 3356 3357 Notes: 3358 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3359 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3360 3361 Most users should employ the `KSP` interface for linear solvers 3362 instead of working directly with matrix algebra routines such as this. 3363 See, e.g., `KSPCreate()`. 3364 3365 Developer Note: 3366 The Fortran interface is not autogenerated as the 3367 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3368 3369 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3370 `MatGetOrdering()` 3371 @*/ 3372 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3373 { 3374 MatFactorInfo tinfo; 3375 3376 PetscFunctionBegin; 3377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3378 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3379 if (info) PetscAssertPointer(info, 3); 3380 PetscValidType(mat, 1); 3381 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3382 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3383 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3384 MatCheckPreallocated(mat, 1); 3385 if (!info) { 3386 PetscCall(MatFactorInfoInitialize(&tinfo)); 3387 info = &tinfo; 3388 } 3389 3390 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3391 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3392 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3393 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3394 PetscFunctionReturn(PETSC_SUCCESS); 3395 } 3396 3397 /*@ 3398 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3399 of a symmetric matrix. 3400 3401 Collective 3402 3403 Input Parameters: 3404 + fact - the factor matrix obtained with `MatGetFactor()` 3405 . mat - the matrix 3406 . perm - row and column permutations 3407 - info - options for factorization, includes 3408 .vb 3409 fill - expected fill as ratio of original fill. 3410 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3411 Run with the option -info to determine an optimal value to use 3412 .ve 3413 3414 Level: developer 3415 3416 Notes: 3417 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3418 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3419 3420 Most users should employ the `KSP` interface for linear solvers 3421 instead of working directly with matrix algebra routines such as this. 3422 See, e.g., `KSPCreate()`. 3423 3424 Developer Note: 3425 The Fortran interface is not autogenerated as the 3426 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3427 3428 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3429 `MatGetOrdering()` 3430 @*/ 3431 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3432 { 3433 MatFactorInfo tinfo; 3434 3435 PetscFunctionBegin; 3436 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3438 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3439 if (info) PetscAssertPointer(info, 4); 3440 PetscValidType(fact, 1); 3441 PetscValidType(mat, 2); 3442 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3445 MatCheckPreallocated(mat, 2); 3446 if (!info) { 3447 PetscCall(MatFactorInfoInitialize(&tinfo)); 3448 info = &tinfo; 3449 } 3450 3451 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3452 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3453 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3454 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3455 PetscFunctionReturn(PETSC_SUCCESS); 3456 } 3457 3458 /*@ 3459 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3460 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3461 `MatCholeskyFactorSymbolic()`. 3462 3463 Collective 3464 3465 Input Parameters: 3466 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3467 . mat - the initial matrix that is to be factored 3468 - info - options for factorization 3469 3470 Level: developer 3471 3472 Note: 3473 Most users should employ the `KSP` interface for linear solvers 3474 instead of working directly with matrix algebra routines such as this. 3475 See, e.g., `KSPCreate()`. 3476 3477 Developer Note: 3478 The Fortran interface is not autogenerated as the 3479 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3480 3481 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3482 @*/ 3483 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3484 { 3485 MatFactorInfo tinfo; 3486 3487 PetscFunctionBegin; 3488 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3489 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3490 PetscValidType(fact, 1); 3491 PetscValidType(mat, 2); 3492 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3493 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, 3494 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3495 MatCheckPreallocated(mat, 2); 3496 if (!info) { 3497 PetscCall(MatFactorInfoInitialize(&tinfo)); 3498 info = &tinfo; 3499 } 3500 3501 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3502 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3503 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3504 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3505 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3506 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3507 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3508 PetscFunctionReturn(PETSC_SUCCESS); 3509 } 3510 3511 /*@ 3512 MatQRFactor - Performs in-place QR factorization of matrix. 3513 3514 Collective 3515 3516 Input Parameters: 3517 + mat - the matrix 3518 . col - column permutation 3519 - info - options for factorization, includes 3520 .vb 3521 fill - expected fill as ratio of original fill. 3522 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3523 Run with the option -info to determine an optimal value to use 3524 .ve 3525 3526 Level: developer 3527 3528 Notes: 3529 Most users should employ the `KSP` interface for linear solvers 3530 instead of working directly with matrix algebra routines such as this. 3531 See, e.g., `KSPCreate()`. 3532 3533 This changes the state of the matrix to a factored matrix; it cannot be used 3534 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3535 3536 Developer Note: 3537 The Fortran interface is not autogenerated as the 3538 interface definition cannot be generated correctly [due to MatFactorInfo] 3539 3540 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3541 `MatSetUnfactored()` 3542 @*/ 3543 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3544 { 3545 PetscFunctionBegin; 3546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3547 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3548 if (info) PetscAssertPointer(info, 3); 3549 PetscValidType(mat, 1); 3550 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3551 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3552 MatCheckPreallocated(mat, 1); 3553 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3554 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3555 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3556 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3557 PetscFunctionReturn(PETSC_SUCCESS); 3558 } 3559 3560 /*@ 3561 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3562 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3563 3564 Collective 3565 3566 Input Parameters: 3567 + fact - the factor matrix obtained with `MatGetFactor()` 3568 . mat - the matrix 3569 . col - column permutation 3570 - info - options for factorization, includes 3571 .vb 3572 fill - expected fill as ratio of original fill. 3573 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3574 Run with the option -info to determine an optimal value to use 3575 .ve 3576 3577 Level: developer 3578 3579 Note: 3580 Most users should employ the `KSP` interface for linear solvers 3581 instead of working directly with matrix algebra routines such as this. 3582 See, e.g., `KSPCreate()`. 3583 3584 Developer Note: 3585 The Fortran interface is not autogenerated as the 3586 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3587 3588 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3589 @*/ 3590 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3591 { 3592 MatFactorInfo tinfo; 3593 3594 PetscFunctionBegin; 3595 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3597 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3598 if (info) PetscAssertPointer(info, 4); 3599 PetscValidType(fact, 1); 3600 PetscValidType(mat, 2); 3601 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3602 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3603 MatCheckPreallocated(mat, 2); 3604 if (!info) { 3605 PetscCall(MatFactorInfoInitialize(&tinfo)); 3606 info = &tinfo; 3607 } 3608 3609 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3610 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3611 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3612 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3613 PetscFunctionReturn(PETSC_SUCCESS); 3614 } 3615 3616 /*@ 3617 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3618 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3619 3620 Collective 3621 3622 Input Parameters: 3623 + fact - the factor matrix obtained with `MatGetFactor()` 3624 . mat - the matrix 3625 - info - options for factorization 3626 3627 Level: developer 3628 3629 Notes: 3630 See `MatQRFactor()` for in-place factorization. 3631 3632 Most users should employ the `KSP` interface for linear solvers 3633 instead of working directly with matrix algebra routines such as this. 3634 See, e.g., `KSPCreate()`. 3635 3636 Developer Note: 3637 The Fortran interface is not autogenerated as the 3638 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3639 3640 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3641 @*/ 3642 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3643 { 3644 MatFactorInfo tinfo; 3645 3646 PetscFunctionBegin; 3647 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3649 PetscValidType(fact, 1); 3650 PetscValidType(mat, 2); 3651 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3652 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, 3653 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3654 3655 MatCheckPreallocated(mat, 2); 3656 if (!info) { 3657 PetscCall(MatFactorInfoInitialize(&tinfo)); 3658 info = &tinfo; 3659 } 3660 3661 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3662 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3663 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3664 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3665 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3666 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3667 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3668 PetscFunctionReturn(PETSC_SUCCESS); 3669 } 3670 3671 /*@ 3672 MatSolve - Solves $A x = b$, given a factored matrix. 3673 3674 Neighbor-wise Collective 3675 3676 Input Parameters: 3677 + mat - the factored matrix 3678 - b - the right-hand-side vector 3679 3680 Output Parameter: 3681 . x - the result vector 3682 3683 Level: developer 3684 3685 Notes: 3686 The vectors `b` and `x` cannot be the same. I.e., one cannot 3687 call `MatSolve`(A,x,x). 3688 3689 Most users should employ the `KSP` interface for linear solvers 3690 instead of working directly with matrix algebra routines such as this. 3691 See, e.g., `KSPCreate()`. 3692 3693 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3694 @*/ 3695 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3696 { 3697 PetscFunctionBegin; 3698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3699 PetscValidType(mat, 1); 3700 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3701 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3702 PetscCheckSameComm(mat, 1, b, 2); 3703 PetscCheckSameComm(mat, 1, x, 3); 3704 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3705 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); 3706 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); 3707 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); 3708 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3709 MatCheckPreallocated(mat, 1); 3710 3711 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3712 PetscCall(VecFlag(x, mat->factorerrortype)); 3713 if (mat->factorerrortype) { 3714 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3715 } else PetscUseTypeMethod(mat, solve, b, x); 3716 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3717 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3718 PetscFunctionReturn(PETSC_SUCCESS); 3719 } 3720 3721 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3722 { 3723 Vec b, x; 3724 PetscInt N, i; 3725 PetscErrorCode (*f)(Mat, Vec, Vec); 3726 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3727 3728 PetscFunctionBegin; 3729 if (A->factorerrortype) { 3730 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3731 PetscCall(MatSetInf(X)); 3732 PetscFunctionReturn(PETSC_SUCCESS); 3733 } 3734 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3735 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3736 PetscCall(MatBoundToCPU(A, &Abound)); 3737 if (!Abound) { 3738 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3739 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3740 } 3741 #if PetscDefined(HAVE_CUDA) 3742 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3743 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3744 #elif PetscDefined(HAVE_HIP) 3745 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3746 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3747 #endif 3748 PetscCall(MatGetSize(B, NULL, &N)); 3749 for (i = 0; i < N; i++) { 3750 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3751 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3752 PetscCall((*f)(A, b, x)); 3753 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3754 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3755 } 3756 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3757 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3758 PetscFunctionReturn(PETSC_SUCCESS); 3759 } 3760 3761 /*@ 3762 MatMatSolve - Solves $A X = B$, given a factored matrix. 3763 3764 Neighbor-wise Collective 3765 3766 Input Parameters: 3767 + A - the factored matrix 3768 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3769 3770 Output Parameter: 3771 . X - the result matrix (dense matrix) 3772 3773 Level: developer 3774 3775 Note: 3776 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3777 otherwise, `B` and `X` cannot be the same. 3778 3779 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3780 @*/ 3781 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3782 { 3783 PetscFunctionBegin; 3784 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3785 PetscValidType(A, 1); 3786 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3787 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3788 PetscCheckSameComm(A, 1, B, 2); 3789 PetscCheckSameComm(A, 1, X, 3); 3790 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); 3791 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); 3792 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"); 3793 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3794 MatCheckPreallocated(A, 1); 3795 3796 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3797 if (!A->ops->matsolve) { 3798 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3799 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3800 } else PetscUseTypeMethod(A, matsolve, B, X); 3801 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3802 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3803 PetscFunctionReturn(PETSC_SUCCESS); 3804 } 3805 3806 /*@ 3807 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3808 3809 Neighbor-wise Collective 3810 3811 Input Parameters: 3812 + A - the factored matrix 3813 - B - the right-hand-side matrix (`MATDENSE` matrix) 3814 3815 Output Parameter: 3816 . X - the result matrix (dense matrix) 3817 3818 Level: developer 3819 3820 Note: 3821 The matrices `B` and `X` cannot be the same. I.e., one cannot 3822 call `MatMatSolveTranspose`(A,X,X). 3823 3824 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3825 @*/ 3826 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3827 { 3828 PetscFunctionBegin; 3829 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3830 PetscValidType(A, 1); 3831 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3832 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3833 PetscCheckSameComm(A, 1, B, 2); 3834 PetscCheckSameComm(A, 1, X, 3); 3835 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3836 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); 3837 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); 3838 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); 3839 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"); 3840 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3841 MatCheckPreallocated(A, 1); 3842 3843 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3844 if (!A->ops->matsolvetranspose) { 3845 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3846 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3847 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3848 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3849 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3850 PetscFunctionReturn(PETSC_SUCCESS); 3851 } 3852 3853 /*@ 3854 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3855 3856 Neighbor-wise Collective 3857 3858 Input Parameters: 3859 + A - the factored matrix 3860 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3861 3862 Output Parameter: 3863 . X - the result matrix (dense matrix) 3864 3865 Level: developer 3866 3867 Note: 3868 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 3869 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3870 3871 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3872 @*/ 3873 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3874 { 3875 PetscFunctionBegin; 3876 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3877 PetscValidType(A, 1); 3878 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3879 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3880 PetscCheckSameComm(A, 1, Bt, 2); 3881 PetscCheckSameComm(A, 1, X, 3); 3882 3883 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3884 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); 3885 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); 3886 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"); 3887 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3888 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3889 MatCheckPreallocated(A, 1); 3890 3891 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3892 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3893 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3894 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3895 PetscFunctionReturn(PETSC_SUCCESS); 3896 } 3897 3898 /*@ 3899 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3900 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3901 3902 Neighbor-wise Collective 3903 3904 Input Parameters: 3905 + mat - the factored matrix 3906 - b - the right-hand-side vector 3907 3908 Output Parameter: 3909 . x - the result vector 3910 3911 Level: developer 3912 3913 Notes: 3914 `MatSolve()` should be used for most applications, as it performs 3915 a forward solve followed by a backward solve. 3916 3917 The vectors `b` and `x` cannot be the same, i.e., one cannot 3918 call `MatForwardSolve`(A,x,x). 3919 3920 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3921 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3922 `MatForwardSolve()` solves $U^T*D y = b$, and 3923 `MatBackwardSolve()` solves $U x = y$. 3924 Thus they do not provide a symmetric preconditioner. 3925 3926 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3927 @*/ 3928 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3929 { 3930 PetscFunctionBegin; 3931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3932 PetscValidType(mat, 1); 3933 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3934 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3935 PetscCheckSameComm(mat, 1, b, 2); 3936 PetscCheckSameComm(mat, 1, x, 3); 3937 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3938 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); 3939 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); 3940 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); 3941 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3942 MatCheckPreallocated(mat, 1); 3943 3944 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3945 PetscUseTypeMethod(mat, forwardsolve, b, x); 3946 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3947 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3948 PetscFunctionReturn(PETSC_SUCCESS); 3949 } 3950 3951 /*@ 3952 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3953 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3954 3955 Neighbor-wise Collective 3956 3957 Input Parameters: 3958 + mat - the factored matrix 3959 - b - the right-hand-side vector 3960 3961 Output Parameter: 3962 . x - the result vector 3963 3964 Level: developer 3965 3966 Notes: 3967 `MatSolve()` should be used for most applications, as it performs 3968 a forward solve followed by a backward solve. 3969 3970 The vectors `b` and `x` cannot be the same. I.e., one cannot 3971 call `MatBackwardSolve`(A,x,x). 3972 3973 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3974 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3975 `MatForwardSolve()` solves $U^T*D y = b$, and 3976 `MatBackwardSolve()` solves $U x = y$. 3977 Thus they do not provide a symmetric preconditioner. 3978 3979 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3980 @*/ 3981 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3982 { 3983 PetscFunctionBegin; 3984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3985 PetscValidType(mat, 1); 3986 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3987 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3988 PetscCheckSameComm(mat, 1, b, 2); 3989 PetscCheckSameComm(mat, 1, x, 3); 3990 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3991 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); 3992 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); 3993 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); 3994 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3995 MatCheckPreallocated(mat, 1); 3996 3997 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3998 PetscUseTypeMethod(mat, backwardsolve, b, x); 3999 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 4000 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4001 PetscFunctionReturn(PETSC_SUCCESS); 4002 } 4003 4004 /*@ 4005 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4006 4007 Neighbor-wise Collective 4008 4009 Input Parameters: 4010 + mat - the factored matrix 4011 . b - the right-hand-side vector 4012 - y - the vector to be added to 4013 4014 Output Parameter: 4015 . x - the result vector 4016 4017 Level: developer 4018 4019 Note: 4020 The vectors `b` and `x` cannot be the same. I.e., one cannot 4021 call `MatSolveAdd`(A,x,y,x). 4022 4023 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4024 @*/ 4025 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4026 { 4027 PetscScalar one = 1.0; 4028 Vec tmp; 4029 4030 PetscFunctionBegin; 4031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4032 PetscValidType(mat, 1); 4033 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4034 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4035 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4036 PetscCheckSameComm(mat, 1, b, 2); 4037 PetscCheckSameComm(mat, 1, y, 3); 4038 PetscCheckSameComm(mat, 1, x, 4); 4039 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4040 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); 4041 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); 4042 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); 4043 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); 4044 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); 4045 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4046 MatCheckPreallocated(mat, 1); 4047 4048 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4049 PetscCall(VecFlag(x, mat->factorerrortype)); 4050 if (mat->factorerrortype) { 4051 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4052 } else if (mat->ops->solveadd) { 4053 PetscUseTypeMethod(mat, solveadd, b, y, x); 4054 } else { 4055 /* do the solve then the add manually */ 4056 if (x != y) { 4057 PetscCall(MatSolve(mat, b, x)); 4058 PetscCall(VecAXPY(x, one, y)); 4059 } else { 4060 PetscCall(VecDuplicate(x, &tmp)); 4061 PetscCall(VecCopy(x, tmp)); 4062 PetscCall(MatSolve(mat, b, x)); 4063 PetscCall(VecAXPY(x, one, tmp)); 4064 PetscCall(VecDestroy(&tmp)); 4065 } 4066 } 4067 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4068 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4069 PetscFunctionReturn(PETSC_SUCCESS); 4070 } 4071 4072 /*@ 4073 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4074 4075 Neighbor-wise Collective 4076 4077 Input Parameters: 4078 + mat - the factored matrix 4079 - b - the right-hand-side vector 4080 4081 Output Parameter: 4082 . x - the result vector 4083 4084 Level: developer 4085 4086 Notes: 4087 The vectors `b` and `x` cannot be the same. I.e., one cannot 4088 call `MatSolveTranspose`(A,x,x). 4089 4090 Most users should employ the `KSP` interface for linear solvers 4091 instead of working directly with matrix algebra routines such as this. 4092 See, e.g., `KSPCreate()`. 4093 4094 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4095 @*/ 4096 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4097 { 4098 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4099 4100 PetscFunctionBegin; 4101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4102 PetscValidType(mat, 1); 4103 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4104 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4105 PetscCheckSameComm(mat, 1, b, 2); 4106 PetscCheckSameComm(mat, 1, x, 3); 4107 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4108 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); 4109 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); 4110 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4111 MatCheckPreallocated(mat, 1); 4112 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4113 PetscCall(VecFlag(x, mat->factorerrortype)); 4114 if (mat->factorerrortype) { 4115 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4116 } else { 4117 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4118 PetscCall((*f)(mat, b, x)); 4119 } 4120 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4121 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4122 PetscFunctionReturn(PETSC_SUCCESS); 4123 } 4124 4125 /*@ 4126 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4127 factored matrix. 4128 4129 Neighbor-wise Collective 4130 4131 Input Parameters: 4132 + mat - the factored matrix 4133 . b - the right-hand-side vector 4134 - y - the vector to be added to 4135 4136 Output Parameter: 4137 . x - the result vector 4138 4139 Level: developer 4140 4141 Note: 4142 The vectors `b` and `x` cannot be the same. I.e., one cannot 4143 call `MatSolveTransposeAdd`(A,x,y,x). 4144 4145 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4146 @*/ 4147 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4148 { 4149 PetscScalar one = 1.0; 4150 Vec tmp; 4151 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4152 4153 PetscFunctionBegin; 4154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4155 PetscValidType(mat, 1); 4156 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4157 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4158 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4159 PetscCheckSameComm(mat, 1, b, 2); 4160 PetscCheckSameComm(mat, 1, y, 3); 4161 PetscCheckSameComm(mat, 1, x, 4); 4162 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4163 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); 4164 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); 4165 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); 4166 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); 4167 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4168 MatCheckPreallocated(mat, 1); 4169 4170 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4171 PetscCall(VecFlag(x, mat->factorerrortype)); 4172 if (mat->factorerrortype) { 4173 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4174 } else if (f) { 4175 PetscCall((*f)(mat, b, y, x)); 4176 } else { 4177 /* do the solve then the add manually */ 4178 if (x != y) { 4179 PetscCall(MatSolveTranspose(mat, b, x)); 4180 PetscCall(VecAXPY(x, one, y)); 4181 } else { 4182 PetscCall(VecDuplicate(x, &tmp)); 4183 PetscCall(VecCopy(x, tmp)); 4184 PetscCall(MatSolveTranspose(mat, b, x)); 4185 PetscCall(VecAXPY(x, one, tmp)); 4186 PetscCall(VecDestroy(&tmp)); 4187 } 4188 } 4189 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4190 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4191 PetscFunctionReturn(PETSC_SUCCESS); 4192 } 4193 4194 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4195 /*@ 4196 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4197 4198 Neighbor-wise Collective 4199 4200 Input Parameters: 4201 + mat - the matrix 4202 . b - the right-hand side 4203 . omega - the relaxation factor 4204 . flag - flag indicating the type of SOR (see below) 4205 . shift - diagonal shift 4206 . its - the number of iterations 4207 - lits - the number of local iterations 4208 4209 Output Parameter: 4210 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4211 4212 SOR Flags: 4213 + `SOR_FORWARD_SWEEP` - forward SOR 4214 . `SOR_BACKWARD_SWEEP` - backward SOR 4215 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4216 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4217 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4218 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4219 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4220 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4221 upper/lower triangular part of matrix to 4222 vector (with omega) 4223 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4224 4225 Level: developer 4226 4227 Notes: 4228 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4229 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4230 on each processor. 4231 4232 Application programmers will not generally use `MatSOR()` directly, 4233 but instead will employ the `KSP`/`PC` interface. 4234 4235 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4236 4237 Most users should employ the `KSP` interface for linear solvers 4238 instead of working directly with matrix algebra routines such as this. 4239 See, e.g., `KSPCreate()`. 4240 4241 Vectors `x` and `b` CANNOT be the same 4242 4243 The flags are implemented as bitwise inclusive or operations. 4244 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4245 to specify a zero initial guess for SSOR. 4246 4247 Developer Note: 4248 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4249 4250 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4251 @*/ 4252 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4253 { 4254 PetscFunctionBegin; 4255 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4256 PetscValidType(mat, 1); 4257 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4258 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4259 PetscCheckSameComm(mat, 1, b, 2); 4260 PetscCheckSameComm(mat, 1, x, 8); 4261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4263 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); 4264 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); 4265 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); 4266 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4267 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4268 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4269 4270 MatCheckPreallocated(mat, 1); 4271 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4272 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4273 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4274 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4275 PetscFunctionReturn(PETSC_SUCCESS); 4276 } 4277 4278 /* 4279 Default matrix copy routine. 4280 */ 4281 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4282 { 4283 PetscInt i, rstart = 0, rend = 0, nz; 4284 const PetscInt *cwork; 4285 const PetscScalar *vwork; 4286 4287 PetscFunctionBegin; 4288 if (B->assembled) PetscCall(MatZeroEntries(B)); 4289 if (str == SAME_NONZERO_PATTERN) { 4290 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4291 for (i = rstart; i < rend; i++) { 4292 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4293 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4294 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4295 } 4296 } else { 4297 PetscCall(MatAYPX(B, 0.0, A, str)); 4298 } 4299 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4300 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4301 PetscFunctionReturn(PETSC_SUCCESS); 4302 } 4303 4304 /*@ 4305 MatCopy - Copies a matrix to another matrix. 4306 4307 Collective 4308 4309 Input Parameters: 4310 + A - the matrix 4311 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4312 4313 Output Parameter: 4314 . B - where the copy is put 4315 4316 Level: intermediate 4317 4318 Notes: 4319 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4320 4321 `MatCopy()` copies the matrix entries of a matrix to another existing 4322 matrix (after first zeroing the second matrix). A related routine is 4323 `MatConvert()`, which first creates a new matrix and then copies the data. 4324 4325 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4326 @*/ 4327 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4328 { 4329 PetscInt i; 4330 4331 PetscFunctionBegin; 4332 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4333 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4334 PetscValidType(A, 1); 4335 PetscValidType(B, 2); 4336 PetscCheckSameComm(A, 1, B, 2); 4337 MatCheckPreallocated(B, 2); 4338 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4339 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4340 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, 4341 A->cmap->N, B->cmap->N); 4342 MatCheckPreallocated(A, 1); 4343 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4344 4345 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4346 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4347 else PetscCall(MatCopy_Basic(A, B, str)); 4348 4349 B->stencil.dim = A->stencil.dim; 4350 B->stencil.noc = A->stencil.noc; 4351 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4352 B->stencil.dims[i] = A->stencil.dims[i]; 4353 B->stencil.starts[i] = A->stencil.starts[i]; 4354 } 4355 4356 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4357 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4358 PetscFunctionReturn(PETSC_SUCCESS); 4359 } 4360 4361 /*@ 4362 MatConvert - Converts a matrix to another matrix, either of the same 4363 or different type. 4364 4365 Collective 4366 4367 Input Parameters: 4368 + mat - the matrix 4369 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4370 same type as the original matrix. 4371 - reuse - denotes if the destination matrix is to be created or reused. 4372 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 4373 `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). 4374 4375 Output Parameter: 4376 . M - pointer to place new matrix 4377 4378 Level: intermediate 4379 4380 Notes: 4381 `MatConvert()` first creates a new matrix and then copies the data from 4382 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4383 entries of one matrix to another already existing matrix context. 4384 4385 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4386 the MPI communicator of the generated matrix is always the same as the communicator 4387 of the input matrix. 4388 4389 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4390 @*/ 4391 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4392 { 4393 PetscBool sametype, issame, flg; 4394 PetscBool3 issymmetric, ishermitian; 4395 char convname[256], mtype[256]; 4396 Mat B; 4397 4398 PetscFunctionBegin; 4399 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4400 PetscValidType(mat, 1); 4401 PetscAssertPointer(M, 4); 4402 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4403 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4404 MatCheckPreallocated(mat, 1); 4405 4406 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4407 if (flg) newtype = mtype; 4408 4409 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4410 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4411 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4412 if (reuse == MAT_REUSE_MATRIX) { 4413 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4414 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4415 } 4416 4417 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4418 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4419 PetscFunctionReturn(PETSC_SUCCESS); 4420 } 4421 4422 /* Cache Mat options because some converters use MatHeaderReplace */ 4423 issymmetric = mat->symmetric; 4424 ishermitian = mat->hermitian; 4425 4426 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4427 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4428 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4429 } else { 4430 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4431 const char *prefix[3] = {"seq", "mpi", ""}; 4432 PetscInt i; 4433 /* 4434 Order of precedence: 4435 0) See if newtype is a superclass of the current matrix. 4436 1) See if a specialized converter is known to the current matrix. 4437 2) See if a specialized converter is known to the desired matrix class. 4438 3) See if a good general converter is registered for the desired class 4439 (as of 6/27/03 only MATMPIADJ falls into this category). 4440 4) See if a good general converter is known for the current matrix. 4441 5) Use a really basic converter. 4442 */ 4443 4444 /* 0) See if newtype is a superclass of the current matrix. 4445 i.e mat is mpiaij and newtype is aij */ 4446 for (i = 0; i < 2; i++) { 4447 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4448 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4449 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4450 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4451 if (flg) { 4452 if (reuse == MAT_INPLACE_MATRIX) { 4453 PetscCall(PetscInfo(mat, "Early return\n")); 4454 PetscFunctionReturn(PETSC_SUCCESS); 4455 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4456 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4457 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4458 PetscFunctionReturn(PETSC_SUCCESS); 4459 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4460 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4461 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4462 PetscFunctionReturn(PETSC_SUCCESS); 4463 } 4464 } 4465 } 4466 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4467 for (i = 0; i < 3; i++) { 4468 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4469 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4470 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4471 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4472 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4473 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4474 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4475 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4476 if (conv) goto foundconv; 4477 } 4478 4479 /* 2) See if a specialized converter is known to the desired matrix class. */ 4480 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4481 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4482 PetscCall(MatSetType(B, newtype)); 4483 for (i = 0; i < 3; i++) { 4484 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4485 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4486 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4487 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4488 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4489 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4490 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4491 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4492 if (conv) { 4493 PetscCall(MatDestroy(&B)); 4494 goto foundconv; 4495 } 4496 } 4497 4498 /* 3) See if a good general converter is registered for the desired class */ 4499 conv = B->ops->convertfrom; 4500 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4501 PetscCall(MatDestroy(&B)); 4502 if (conv) goto foundconv; 4503 4504 /* 4) See if a good general converter is known for the current matrix */ 4505 if (mat->ops->convert) conv = mat->ops->convert; 4506 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4507 if (conv) goto foundconv; 4508 4509 /* 5) Use a really basic converter. */ 4510 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4511 conv = MatConvert_Basic; 4512 4513 foundconv: 4514 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4515 PetscCall((*conv)(mat, newtype, reuse, M)); 4516 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4517 /* the block sizes must be same if the mappings are copied over */ 4518 (*M)->rmap->bs = mat->rmap->bs; 4519 (*M)->cmap->bs = mat->cmap->bs; 4520 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4521 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4522 (*M)->rmap->mapping = mat->rmap->mapping; 4523 (*M)->cmap->mapping = mat->cmap->mapping; 4524 } 4525 (*M)->stencil.dim = mat->stencil.dim; 4526 (*M)->stencil.noc = mat->stencil.noc; 4527 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4528 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4529 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4530 } 4531 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4532 } 4533 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4534 4535 /* Copy Mat options */ 4536 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4537 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4538 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4539 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4540 PetscFunctionReturn(PETSC_SUCCESS); 4541 } 4542 4543 /*@ 4544 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4545 4546 Not Collective 4547 4548 Input Parameter: 4549 . mat - the matrix, must be a factored matrix 4550 4551 Output Parameter: 4552 . type - the string name of the package (do not free this string) 4553 4554 Level: intermediate 4555 4556 Fortran Note: 4557 Pass in an empty string that is long enough and the package name will be copied into it. 4558 4559 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4560 @*/ 4561 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4562 { 4563 PetscErrorCode (*conv)(Mat, MatSolverType *); 4564 4565 PetscFunctionBegin; 4566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4567 PetscValidType(mat, 1); 4568 PetscAssertPointer(type, 2); 4569 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4570 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4571 if (conv) PetscCall((*conv)(mat, type)); 4572 else *type = MATSOLVERPETSC; 4573 PetscFunctionReturn(PETSC_SUCCESS); 4574 } 4575 4576 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4577 struct _MatSolverTypeForSpecifcType { 4578 MatType mtype; 4579 /* no entry for MAT_FACTOR_NONE */ 4580 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4581 MatSolverTypeForSpecifcType next; 4582 }; 4583 4584 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4585 struct _MatSolverTypeHolder { 4586 char *name; 4587 MatSolverTypeForSpecifcType handlers; 4588 MatSolverTypeHolder next; 4589 }; 4590 4591 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4592 4593 /*@C 4594 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4595 4596 Logically Collective, No Fortran Support 4597 4598 Input Parameters: 4599 + package - name of the package, for example petsc or superlu 4600 . mtype - the matrix type that works with this package 4601 . ftype - the type of factorization supported by the package 4602 - createfactor - routine that will create the factored matrix ready to be used 4603 4604 Level: developer 4605 4606 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4607 `MatGetFactor()` 4608 @*/ 4609 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4610 { 4611 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4612 PetscBool flg; 4613 MatSolverTypeForSpecifcType inext, iprev = NULL; 4614 4615 PetscFunctionBegin; 4616 PetscCall(MatInitializePackage()); 4617 if (!next) { 4618 PetscCall(PetscNew(&MatSolverTypeHolders)); 4619 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4620 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4621 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4622 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4623 PetscFunctionReturn(PETSC_SUCCESS); 4624 } 4625 while (next) { 4626 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4627 if (flg) { 4628 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4629 inext = next->handlers; 4630 while (inext) { 4631 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4632 if (flg) { 4633 inext->createfactor[(int)ftype - 1] = createfactor; 4634 PetscFunctionReturn(PETSC_SUCCESS); 4635 } 4636 iprev = inext; 4637 inext = inext->next; 4638 } 4639 PetscCall(PetscNew(&iprev->next)); 4640 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4641 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4642 PetscFunctionReturn(PETSC_SUCCESS); 4643 } 4644 prev = next; 4645 next = next->next; 4646 } 4647 PetscCall(PetscNew(&prev->next)); 4648 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4649 PetscCall(PetscNew(&prev->next->handlers)); 4650 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4651 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4652 PetscFunctionReturn(PETSC_SUCCESS); 4653 } 4654 4655 /*@C 4656 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4657 4658 Input Parameters: 4659 + 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 4660 . ftype - the type of factorization supported by the type 4661 - mtype - the matrix type that works with this type 4662 4663 Output Parameters: 4664 + foundtype - `PETSC_TRUE` if the type was registered 4665 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4666 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4667 4668 Calling sequence of `createfactor`: 4669 + A - the matrix providing the factor matrix 4670 . ftype - the `MatFactorType` of the factor requested 4671 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4672 4673 Level: developer 4674 4675 Note: 4676 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4677 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4678 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4679 4680 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4681 `MatInitializePackage()` 4682 @*/ 4683 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4684 { 4685 MatSolverTypeHolder next = MatSolverTypeHolders; 4686 PetscBool flg; 4687 MatSolverTypeForSpecifcType inext; 4688 4689 PetscFunctionBegin; 4690 if (foundtype) *foundtype = PETSC_FALSE; 4691 if (foundmtype) *foundmtype = PETSC_FALSE; 4692 if (createfactor) *createfactor = NULL; 4693 4694 if (type) { 4695 while (next) { 4696 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4697 if (flg) { 4698 if (foundtype) *foundtype = PETSC_TRUE; 4699 inext = next->handlers; 4700 while (inext) { 4701 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4702 if (flg) { 4703 if (foundmtype) *foundmtype = PETSC_TRUE; 4704 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4705 PetscFunctionReturn(PETSC_SUCCESS); 4706 } 4707 inext = inext->next; 4708 } 4709 } 4710 next = next->next; 4711 } 4712 } else { 4713 while (next) { 4714 inext = next->handlers; 4715 while (inext) { 4716 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4717 if (flg && inext->createfactor[(int)ftype - 1]) { 4718 if (foundtype) *foundtype = PETSC_TRUE; 4719 if (foundmtype) *foundmtype = PETSC_TRUE; 4720 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4721 PetscFunctionReturn(PETSC_SUCCESS); 4722 } 4723 inext = inext->next; 4724 } 4725 next = next->next; 4726 } 4727 /* try with base classes inext->mtype */ 4728 next = MatSolverTypeHolders; 4729 while (next) { 4730 inext = next->handlers; 4731 while (inext) { 4732 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4733 if (flg && inext->createfactor[(int)ftype - 1]) { 4734 if (foundtype) *foundtype = PETSC_TRUE; 4735 if (foundmtype) *foundmtype = PETSC_TRUE; 4736 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4737 PetscFunctionReturn(PETSC_SUCCESS); 4738 } 4739 inext = inext->next; 4740 } 4741 next = next->next; 4742 } 4743 } 4744 PetscFunctionReturn(PETSC_SUCCESS); 4745 } 4746 4747 PetscErrorCode MatSolverTypeDestroy(void) 4748 { 4749 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4750 MatSolverTypeForSpecifcType inext, iprev; 4751 4752 PetscFunctionBegin; 4753 while (next) { 4754 PetscCall(PetscFree(next->name)); 4755 inext = next->handlers; 4756 while (inext) { 4757 PetscCall(PetscFree(inext->mtype)); 4758 iprev = inext; 4759 inext = inext->next; 4760 PetscCall(PetscFree(iprev)); 4761 } 4762 prev = next; 4763 next = next->next; 4764 PetscCall(PetscFree(prev)); 4765 } 4766 MatSolverTypeHolders = NULL; 4767 PetscFunctionReturn(PETSC_SUCCESS); 4768 } 4769 4770 /*@ 4771 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4772 4773 Logically Collective 4774 4775 Input Parameter: 4776 . mat - the matrix 4777 4778 Output Parameter: 4779 . flg - `PETSC_TRUE` if uses the ordering 4780 4781 Level: developer 4782 4783 Note: 4784 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4785 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4786 4787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4788 @*/ 4789 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4790 { 4791 PetscFunctionBegin; 4792 *flg = mat->canuseordering; 4793 PetscFunctionReturn(PETSC_SUCCESS); 4794 } 4795 4796 /*@ 4797 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4798 4799 Logically Collective 4800 4801 Input Parameters: 4802 + mat - the matrix obtained with `MatGetFactor()` 4803 - ftype - the factorization type to be used 4804 4805 Output Parameter: 4806 . otype - the preferred ordering type 4807 4808 Level: developer 4809 4810 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4811 @*/ 4812 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4813 { 4814 PetscFunctionBegin; 4815 *otype = mat->preferredordering[ftype]; 4816 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4817 PetscFunctionReturn(PETSC_SUCCESS); 4818 } 4819 4820 /*@ 4821 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4822 4823 Collective 4824 4825 Input Parameters: 4826 + mat - the matrix 4827 . 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 4828 the other criteria is returned 4829 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4830 4831 Output Parameter: 4832 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4833 4834 Options Database Keys: 4835 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4836 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4837 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4838 4839 Level: intermediate 4840 4841 Notes: 4842 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4843 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4844 4845 Users usually access the factorization solvers via `KSP` 4846 4847 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4848 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 4849 4850 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4851 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4852 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4853 4854 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4855 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4856 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4857 4858 Developer Note: 4859 This should actually be called `MatCreateFactor()` since it creates a new factor object 4860 4861 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4862 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4863 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4864 @*/ 4865 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4866 { 4867 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4868 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4869 4870 PetscFunctionBegin; 4871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4872 PetscValidType(mat, 1); 4873 4874 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4875 MatCheckPreallocated(mat, 1); 4876 4877 PetscCall(MatIsShell(mat, &shell)); 4878 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4879 if (hasop) { 4880 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4881 PetscFunctionReturn(PETSC_SUCCESS); 4882 } 4883 4884 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4885 if (!foundtype) { 4886 if (type) { 4887 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], 4888 ((PetscObject)mat)->type_name, type); 4889 } else { 4890 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); 4891 } 4892 } 4893 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4894 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); 4895 4896 PetscCall((*conv)(mat, ftype, f)); 4897 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4898 PetscFunctionReturn(PETSC_SUCCESS); 4899 } 4900 4901 /*@ 4902 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4903 4904 Not Collective 4905 4906 Input Parameters: 4907 + mat - the matrix 4908 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4909 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4910 4911 Output Parameter: 4912 . flg - PETSC_TRUE if the factorization is available 4913 4914 Level: intermediate 4915 4916 Notes: 4917 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4918 such as pastix, superlu, mumps etc. 4919 4920 PETSc must have been ./configure to use the external solver, using the option --download-package 4921 4922 Developer Note: 4923 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4924 4925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4926 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4927 @*/ 4928 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4929 { 4930 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4931 4932 PetscFunctionBegin; 4933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4934 PetscAssertPointer(flg, 4); 4935 4936 *flg = PETSC_FALSE; 4937 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4938 4939 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4940 MatCheckPreallocated(mat, 1); 4941 4942 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4943 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4944 PetscFunctionReturn(PETSC_SUCCESS); 4945 } 4946 4947 /*@ 4948 MatDuplicate - Duplicates a matrix including the non-zero structure. 4949 4950 Collective 4951 4952 Input Parameters: 4953 + mat - the matrix 4954 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4955 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4956 4957 Output Parameter: 4958 . M - pointer to place new matrix 4959 4960 Level: intermediate 4961 4962 Notes: 4963 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4964 4965 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4966 4967 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. 4968 4969 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4970 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4971 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4972 4973 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4974 @*/ 4975 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4976 { 4977 Mat B; 4978 VecType vtype; 4979 PetscInt i; 4980 PetscObject dm, container_h, container_d; 4981 void (*viewf)(void); 4982 4983 PetscFunctionBegin; 4984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4985 PetscValidType(mat, 1); 4986 PetscAssertPointer(M, 3); 4987 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4988 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4989 MatCheckPreallocated(mat, 1); 4990 4991 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4992 PetscUseTypeMethod(mat, duplicate, op, M); 4993 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4994 B = *M; 4995 4996 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4997 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4998 PetscCall(MatGetVecType(mat, &vtype)); 4999 PetscCall(MatSetVecType(B, vtype)); 5000 5001 B->stencil.dim = mat->stencil.dim; 5002 B->stencil.noc = mat->stencil.noc; 5003 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 5004 B->stencil.dims[i] = mat->stencil.dims[i]; 5005 B->stencil.starts[i] = mat->stencil.starts[i]; 5006 } 5007 5008 B->nooffproczerorows = mat->nooffproczerorows; 5009 B->nooffprocentries = mat->nooffprocentries; 5010 5011 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5012 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5013 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5014 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5015 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5016 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5017 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5018 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5019 PetscFunctionReturn(PETSC_SUCCESS); 5020 } 5021 5022 /*@ 5023 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5024 5025 Logically Collective 5026 5027 Input Parameter: 5028 . mat - the matrix 5029 5030 Output Parameter: 5031 . v - the diagonal of the matrix 5032 5033 Level: intermediate 5034 5035 Note: 5036 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5037 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5038 is larger than `ndiag`, the values of the remaining entries are unspecified. 5039 5040 Currently only correct in parallel for square matrices. 5041 5042 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5043 @*/ 5044 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5045 { 5046 PetscFunctionBegin; 5047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5048 PetscValidType(mat, 1); 5049 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5051 MatCheckPreallocated(mat, 1); 5052 if (PetscDefined(USE_DEBUG)) { 5053 PetscInt nv, row, col, ndiag; 5054 5055 PetscCall(VecGetLocalSize(v, &nv)); 5056 PetscCall(MatGetLocalSize(mat, &row, &col)); 5057 ndiag = PetscMin(row, col); 5058 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); 5059 } 5060 5061 PetscUseTypeMethod(mat, getdiagonal, v); 5062 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5063 PetscFunctionReturn(PETSC_SUCCESS); 5064 } 5065 5066 /*@ 5067 MatGetRowMin - Gets the minimum value (of the real part) of each 5068 row of the matrix 5069 5070 Logically Collective 5071 5072 Input Parameter: 5073 . mat - the matrix 5074 5075 Output Parameters: 5076 + v - the vector for storing the maximums 5077 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5078 5079 Level: intermediate 5080 5081 Note: 5082 The result of this call are the same as if one converted the matrix to dense format 5083 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5084 5085 This code is only implemented for a couple of matrix formats. 5086 5087 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5088 `MatGetRowMax()` 5089 @*/ 5090 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5091 { 5092 PetscFunctionBegin; 5093 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5094 PetscValidType(mat, 1); 5095 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5097 5098 if (!mat->cmap->N) { 5099 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5100 if (idx) { 5101 PetscInt i, m = mat->rmap->n; 5102 for (i = 0; i < m; i++) idx[i] = -1; 5103 } 5104 } else { 5105 MatCheckPreallocated(mat, 1); 5106 } 5107 PetscUseTypeMethod(mat, getrowmin, v, idx); 5108 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5109 PetscFunctionReturn(PETSC_SUCCESS); 5110 } 5111 5112 /*@ 5113 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5114 row of the matrix 5115 5116 Logically Collective 5117 5118 Input Parameter: 5119 . mat - the matrix 5120 5121 Output Parameters: 5122 + v - the vector for storing the minimums 5123 - idx - the indices of the column found for each row (or `NULL` if not needed) 5124 5125 Level: intermediate 5126 5127 Notes: 5128 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5129 row is 0 (the first column). 5130 5131 This code is only implemented for a couple of matrix formats. 5132 5133 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5134 @*/ 5135 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5136 { 5137 PetscFunctionBegin; 5138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5139 PetscValidType(mat, 1); 5140 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5141 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5142 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5143 5144 if (!mat->cmap->N) { 5145 PetscCall(VecSet(v, 0.0)); 5146 if (idx) { 5147 PetscInt i, m = mat->rmap->n; 5148 for (i = 0; i < m; i++) idx[i] = -1; 5149 } 5150 } else { 5151 MatCheckPreallocated(mat, 1); 5152 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5153 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5154 } 5155 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5156 PetscFunctionReturn(PETSC_SUCCESS); 5157 } 5158 5159 /*@ 5160 MatGetRowMax - Gets the maximum value (of the real part) of each 5161 row of the matrix 5162 5163 Logically Collective 5164 5165 Input Parameter: 5166 . mat - the matrix 5167 5168 Output Parameters: 5169 + v - the vector for storing the maximums 5170 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5171 5172 Level: intermediate 5173 5174 Notes: 5175 The result of this call are the same as if one converted the matrix to dense format 5176 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5177 5178 This code is only implemented for a couple of matrix formats. 5179 5180 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5181 @*/ 5182 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5183 { 5184 PetscFunctionBegin; 5185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5186 PetscValidType(mat, 1); 5187 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5188 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5189 5190 if (!mat->cmap->N) { 5191 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5192 if (idx) { 5193 PetscInt i, m = mat->rmap->n; 5194 for (i = 0; i < m; i++) idx[i] = -1; 5195 } 5196 } else { 5197 MatCheckPreallocated(mat, 1); 5198 PetscUseTypeMethod(mat, getrowmax, v, idx); 5199 } 5200 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5201 PetscFunctionReturn(PETSC_SUCCESS); 5202 } 5203 5204 /*@ 5205 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5206 row of the matrix 5207 5208 Logically Collective 5209 5210 Input Parameter: 5211 . mat - the matrix 5212 5213 Output Parameters: 5214 + v - the vector for storing the maximums 5215 - idx - the indices of the column found for each row (or `NULL` if not needed) 5216 5217 Level: intermediate 5218 5219 Notes: 5220 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5221 row is 0 (the first column). 5222 5223 This code is only implemented for a couple of matrix formats. 5224 5225 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5226 @*/ 5227 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5228 { 5229 PetscFunctionBegin; 5230 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5231 PetscValidType(mat, 1); 5232 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5233 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5234 5235 if (!mat->cmap->N) { 5236 PetscCall(VecSet(v, 0.0)); 5237 if (idx) { 5238 PetscInt i, m = mat->rmap->n; 5239 for (i = 0; i < m; i++) idx[i] = -1; 5240 } 5241 } else { 5242 MatCheckPreallocated(mat, 1); 5243 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5244 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5245 } 5246 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5247 PetscFunctionReturn(PETSC_SUCCESS); 5248 } 5249 5250 /*@ 5251 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5252 5253 Logically Collective 5254 5255 Input Parameter: 5256 . mat - the matrix 5257 5258 Output Parameter: 5259 . v - the vector for storing the sum 5260 5261 Level: intermediate 5262 5263 This code is only implemented for a couple of matrix formats. 5264 5265 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5266 @*/ 5267 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5268 { 5269 PetscFunctionBegin; 5270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5271 PetscValidType(mat, 1); 5272 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5274 5275 if (!mat->cmap->N) { 5276 PetscCall(VecSet(v, 0.0)); 5277 } else { 5278 MatCheckPreallocated(mat, 1); 5279 PetscUseTypeMethod(mat, getrowsumabs, v); 5280 } 5281 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5282 PetscFunctionReturn(PETSC_SUCCESS); 5283 } 5284 5285 /*@ 5286 MatGetRowSum - Gets the sum of each row of the matrix 5287 5288 Logically or Neighborhood Collective 5289 5290 Input Parameter: 5291 . mat - the matrix 5292 5293 Output Parameter: 5294 . v - the vector for storing the sum of rows 5295 5296 Level: intermediate 5297 5298 Note: 5299 This code is slow since it is not currently specialized for different formats 5300 5301 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5302 @*/ 5303 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5304 { 5305 Vec ones; 5306 5307 PetscFunctionBegin; 5308 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5309 PetscValidType(mat, 1); 5310 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5311 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5312 MatCheckPreallocated(mat, 1); 5313 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5314 PetscCall(VecSet(ones, 1.)); 5315 PetscCall(MatMult(mat, ones, v)); 5316 PetscCall(VecDestroy(&ones)); 5317 PetscFunctionReturn(PETSC_SUCCESS); 5318 } 5319 5320 /*@ 5321 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5322 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5323 5324 Collective 5325 5326 Input Parameter: 5327 . mat - the matrix to provide the transpose 5328 5329 Output Parameter: 5330 . 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 5331 5332 Level: advanced 5333 5334 Note: 5335 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 5336 routine allows bypassing that call. 5337 5338 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5339 @*/ 5340 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5341 { 5342 MatParentState *rb = NULL; 5343 5344 PetscFunctionBegin; 5345 PetscCall(PetscNew(&rb)); 5346 rb->id = ((PetscObject)mat)->id; 5347 rb->state = 0; 5348 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5349 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5350 PetscFunctionReturn(PETSC_SUCCESS); 5351 } 5352 5353 /*@ 5354 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5355 5356 Collective 5357 5358 Input Parameters: 5359 + mat - the matrix to transpose 5360 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5361 5362 Output Parameter: 5363 . B - the transpose of the matrix 5364 5365 Level: intermediate 5366 5367 Notes: 5368 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5369 5370 `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 5371 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5372 5373 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. 5374 5375 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5376 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5377 5378 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5379 5380 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5381 5382 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5383 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5384 @*/ 5385 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5386 { 5387 PetscContainer rB = NULL; 5388 MatParentState *rb = NULL; 5389 5390 PetscFunctionBegin; 5391 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5392 PetscValidType(mat, 1); 5393 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5394 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5395 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5396 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5397 MatCheckPreallocated(mat, 1); 5398 if (reuse == MAT_REUSE_MATRIX) { 5399 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5400 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5401 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5402 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5403 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5404 } 5405 5406 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5407 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5408 PetscUseTypeMethod(mat, transpose, reuse, B); 5409 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5410 } 5411 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5412 5413 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5414 if (reuse != MAT_INPLACE_MATRIX) { 5415 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5416 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5417 rb->state = ((PetscObject)mat)->state; 5418 rb->nonzerostate = mat->nonzerostate; 5419 } 5420 PetscFunctionReturn(PETSC_SUCCESS); 5421 } 5422 5423 /*@ 5424 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5425 5426 Collective 5427 5428 Input Parameter: 5429 . A - the matrix to transpose 5430 5431 Output Parameter: 5432 . 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 5433 numerical portion. 5434 5435 Level: intermediate 5436 5437 Note: 5438 This is not supported for many matrix types, use `MatTranspose()` in those cases 5439 5440 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5441 @*/ 5442 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5443 { 5444 PetscFunctionBegin; 5445 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5446 PetscValidType(A, 1); 5447 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5448 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5449 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5450 PetscUseTypeMethod(A, transposesymbolic, B); 5451 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5452 5453 PetscCall(MatTransposeSetPrecursor(A, *B)); 5454 PetscFunctionReturn(PETSC_SUCCESS); 5455 } 5456 5457 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5458 { 5459 PetscContainer rB; 5460 MatParentState *rb; 5461 5462 PetscFunctionBegin; 5463 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5464 PetscValidType(A, 1); 5465 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5466 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5467 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5468 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5469 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5470 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5471 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5472 PetscFunctionReturn(PETSC_SUCCESS); 5473 } 5474 5475 /*@ 5476 MatIsTranspose - Test whether a matrix is another one's transpose, 5477 or its own, in which case it tests symmetry. 5478 5479 Collective 5480 5481 Input Parameters: 5482 + A - the matrix to test 5483 . B - the matrix to test against, this can equal the first parameter 5484 - tol - tolerance, differences between entries smaller than this are counted as zero 5485 5486 Output Parameter: 5487 . flg - the result 5488 5489 Level: intermediate 5490 5491 Notes: 5492 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5493 test involves parallel copies of the block off-diagonal parts of the matrix. 5494 5495 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5496 @*/ 5497 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5498 { 5499 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5500 5501 PetscFunctionBegin; 5502 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5503 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5504 PetscAssertPointer(flg, 4); 5505 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5506 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5507 *flg = PETSC_FALSE; 5508 if (f && g) { 5509 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5510 PetscCall((*f)(A, B, tol, flg)); 5511 } else { 5512 MatType mattype; 5513 5514 PetscCall(MatGetType(f ? B : A, &mattype)); 5515 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5516 } 5517 PetscFunctionReturn(PETSC_SUCCESS); 5518 } 5519 5520 /*@ 5521 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5522 5523 Collective 5524 5525 Input Parameters: 5526 + mat - the matrix to transpose and complex conjugate 5527 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5528 5529 Output Parameter: 5530 . B - the Hermitian transpose 5531 5532 Level: intermediate 5533 5534 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5535 @*/ 5536 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5537 { 5538 PetscFunctionBegin; 5539 PetscCall(MatTranspose(mat, reuse, B)); 5540 #if defined(PETSC_USE_COMPLEX) 5541 PetscCall(MatConjugate(*B)); 5542 #endif 5543 PetscFunctionReturn(PETSC_SUCCESS); 5544 } 5545 5546 /*@ 5547 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5548 5549 Collective 5550 5551 Input Parameters: 5552 + A - the matrix to test 5553 . B - the matrix to test against, this can equal the first parameter 5554 - tol - tolerance, differences between entries smaller than this are counted as zero 5555 5556 Output Parameter: 5557 . flg - the result 5558 5559 Level: intermediate 5560 5561 Notes: 5562 Only available for `MATAIJ` matrices. 5563 5564 The sequential algorithm 5565 has a running time of the order of the number of nonzeros; the parallel 5566 test involves parallel copies of the block off-diagonal parts of the matrix. 5567 5568 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5569 @*/ 5570 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5571 { 5572 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5573 5574 PetscFunctionBegin; 5575 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5576 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5577 PetscAssertPointer(flg, 4); 5578 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5579 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5580 if (f && g) { 5581 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5582 PetscCall((*f)(A, B, tol, flg)); 5583 } 5584 PetscFunctionReturn(PETSC_SUCCESS); 5585 } 5586 5587 /*@ 5588 MatPermute - Creates a new matrix with rows and columns permuted from the 5589 original. 5590 5591 Collective 5592 5593 Input Parameters: 5594 + mat - the matrix to permute 5595 . row - row permutation, each processor supplies only the permutation for its rows 5596 - col - column permutation, each processor supplies only the permutation for its columns 5597 5598 Output Parameter: 5599 . B - the permuted matrix 5600 5601 Level: advanced 5602 5603 Note: 5604 The index sets map from row/col of permuted matrix to row/col of original matrix. 5605 The index sets should be on the same communicator as mat and have the same local sizes. 5606 5607 Developer Note: 5608 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5609 exploit the fact that row and col are permutations, consider implementing the 5610 more general `MatCreateSubMatrix()` instead. 5611 5612 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5613 @*/ 5614 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5615 { 5616 PetscFunctionBegin; 5617 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5618 PetscValidType(mat, 1); 5619 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5620 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5621 PetscAssertPointer(B, 4); 5622 PetscCheckSameComm(mat, 1, row, 2); 5623 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5624 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5625 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5626 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5627 MatCheckPreallocated(mat, 1); 5628 5629 if (mat->ops->permute) { 5630 PetscUseTypeMethod(mat, permute, row, col, B); 5631 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5632 } else { 5633 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5634 } 5635 PetscFunctionReturn(PETSC_SUCCESS); 5636 } 5637 5638 /*@ 5639 MatEqual - Compares two matrices. 5640 5641 Collective 5642 5643 Input Parameters: 5644 + A - the first matrix 5645 - B - the second matrix 5646 5647 Output Parameter: 5648 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5649 5650 Level: intermediate 5651 5652 Note: 5653 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 5654 using several randomly created vectors, see `MatMultEqual()`. 5655 5656 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5657 @*/ 5658 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5659 { 5660 PetscFunctionBegin; 5661 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5662 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5663 PetscValidType(A, 1); 5664 PetscValidType(B, 2); 5665 PetscAssertPointer(flg, 3); 5666 PetscCheckSameComm(A, 1, B, 2); 5667 MatCheckPreallocated(A, 1); 5668 MatCheckPreallocated(B, 2); 5669 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5670 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5671 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, 5672 B->cmap->N); 5673 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5674 PetscUseTypeMethod(A, equal, B, flg); 5675 } else { 5676 PetscCall(MatMultEqual(A, B, 10, flg)); 5677 } 5678 PetscFunctionReturn(PETSC_SUCCESS); 5679 } 5680 5681 /*@ 5682 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5683 matrices that are stored as vectors. Either of the two scaling 5684 matrices can be `NULL`. 5685 5686 Collective 5687 5688 Input Parameters: 5689 + mat - the matrix to be scaled 5690 . l - the left scaling vector (or `NULL`) 5691 - r - the right scaling vector (or `NULL`) 5692 5693 Level: intermediate 5694 5695 Note: 5696 `MatDiagonalScale()` computes $A = LAR$, where 5697 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5698 The L scales the rows of the matrix, the R scales the columns of the matrix. 5699 5700 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5701 @*/ 5702 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5703 { 5704 PetscFunctionBegin; 5705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5706 PetscValidType(mat, 1); 5707 if (l) { 5708 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5709 PetscCheckSameComm(mat, 1, l, 2); 5710 } 5711 if (r) { 5712 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5713 PetscCheckSameComm(mat, 1, r, 3); 5714 } 5715 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5716 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5717 MatCheckPreallocated(mat, 1); 5718 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5719 5720 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5721 PetscUseTypeMethod(mat, diagonalscale, l, r); 5722 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5723 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5724 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5725 PetscFunctionReturn(PETSC_SUCCESS); 5726 } 5727 5728 /*@ 5729 MatScale - Scales all elements of a matrix by a given number. 5730 5731 Logically Collective 5732 5733 Input Parameters: 5734 + mat - the matrix to be scaled 5735 - a - the scaling value 5736 5737 Level: intermediate 5738 5739 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5740 @*/ 5741 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5742 { 5743 PetscFunctionBegin; 5744 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5745 PetscValidType(mat, 1); 5746 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5747 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5748 PetscValidLogicalCollectiveScalar(mat, a, 2); 5749 MatCheckPreallocated(mat, 1); 5750 5751 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5752 if (a != (PetscScalar)1.0) { 5753 PetscUseTypeMethod(mat, scale, a); 5754 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5755 } 5756 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5757 PetscFunctionReturn(PETSC_SUCCESS); 5758 } 5759 5760 /*@ 5761 MatNorm - Calculates various norms of a matrix. 5762 5763 Collective 5764 5765 Input Parameters: 5766 + mat - the matrix 5767 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5768 5769 Output Parameter: 5770 . nrm - the resulting norm 5771 5772 Level: intermediate 5773 5774 .seealso: [](ch_matrices), `Mat` 5775 @*/ 5776 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5777 { 5778 PetscFunctionBegin; 5779 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5780 PetscValidType(mat, 1); 5781 PetscAssertPointer(nrm, 3); 5782 5783 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5784 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5785 MatCheckPreallocated(mat, 1); 5786 5787 PetscUseTypeMethod(mat, norm, type, nrm); 5788 PetscFunctionReturn(PETSC_SUCCESS); 5789 } 5790 5791 /* 5792 This variable is used to prevent counting of MatAssemblyBegin() that 5793 are called from within a MatAssemblyEnd(). 5794 */ 5795 static PetscInt MatAssemblyEnd_InUse = 0; 5796 /*@ 5797 MatAssemblyBegin - Begins assembling the matrix. This routine should 5798 be called after completing all calls to `MatSetValues()`. 5799 5800 Collective 5801 5802 Input Parameters: 5803 + mat - the matrix 5804 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5805 5806 Level: beginner 5807 5808 Notes: 5809 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5810 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5811 5812 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5813 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5814 using the matrix. 5815 5816 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5817 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 5818 a global collective operation requiring all processes that share the matrix. 5819 5820 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5821 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5822 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5823 5824 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5825 @*/ 5826 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5827 { 5828 PetscFunctionBegin; 5829 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5830 PetscValidType(mat, 1); 5831 MatCheckPreallocated(mat, 1); 5832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5833 if (mat->assembled) { 5834 mat->was_assembled = PETSC_TRUE; 5835 mat->assembled = PETSC_FALSE; 5836 } 5837 5838 if (!MatAssemblyEnd_InUse) { 5839 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5840 PetscTryTypeMethod(mat, assemblybegin, type); 5841 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5842 } else PetscTryTypeMethod(mat, assemblybegin, type); 5843 PetscFunctionReturn(PETSC_SUCCESS); 5844 } 5845 5846 /*@ 5847 MatAssembled - Indicates if a matrix has been assembled and is ready for 5848 use; for example, in matrix-vector product. 5849 5850 Not Collective 5851 5852 Input Parameter: 5853 . mat - the matrix 5854 5855 Output Parameter: 5856 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5857 5858 Level: advanced 5859 5860 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5861 @*/ 5862 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5863 { 5864 PetscFunctionBegin; 5865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5866 PetscAssertPointer(assembled, 2); 5867 *assembled = mat->assembled; 5868 PetscFunctionReturn(PETSC_SUCCESS); 5869 } 5870 5871 /*@ 5872 MatAssemblyEnd - Completes assembling the matrix. This routine should 5873 be called after `MatAssemblyBegin()`. 5874 5875 Collective 5876 5877 Input Parameters: 5878 + mat - the matrix 5879 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5880 5881 Options Database Keys: 5882 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5883 . -mat_view ::ascii_info_detail - Prints more detailed info 5884 . -mat_view - Prints matrix in ASCII format 5885 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5886 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5887 . -display <name> - Sets display name (default is host) 5888 . -draw_pause <sec> - Sets number of seconds to pause after display 5889 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5890 . -viewer_socket_machine <machine> - Machine to use for socket 5891 . -viewer_socket_port <port> - Port number to use for socket 5892 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5893 5894 Level: beginner 5895 5896 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5897 @*/ 5898 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5899 { 5900 static PetscInt inassm = 0; 5901 PetscBool flg = PETSC_FALSE; 5902 5903 PetscFunctionBegin; 5904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5905 PetscValidType(mat, 1); 5906 5907 inassm++; 5908 MatAssemblyEnd_InUse++; 5909 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5910 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5911 PetscTryTypeMethod(mat, assemblyend, type); 5912 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5913 } else PetscTryTypeMethod(mat, assemblyend, type); 5914 5915 /* Flush assembly is not a true assembly */ 5916 if (type != MAT_FLUSH_ASSEMBLY) { 5917 if (mat->num_ass) { 5918 if (!mat->symmetry_eternal) { 5919 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5920 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5921 } 5922 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5923 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5924 } 5925 mat->num_ass++; 5926 mat->assembled = PETSC_TRUE; 5927 mat->ass_nonzerostate = mat->nonzerostate; 5928 } 5929 5930 mat->insertmode = NOT_SET_VALUES; 5931 MatAssemblyEnd_InUse--; 5932 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5933 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5934 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5935 5936 if (mat->checksymmetryonassembly) { 5937 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5938 if (flg) { 5939 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5940 } else { 5941 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5942 } 5943 } 5944 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5945 } 5946 inassm--; 5947 PetscFunctionReturn(PETSC_SUCCESS); 5948 } 5949 5950 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5951 /*@ 5952 MatSetOption - Sets a parameter option for a matrix. Some options 5953 may be specific to certain storage formats. Some options 5954 determine how values will be inserted (or added). Sorted, 5955 row-oriented input will generally assemble the fastest. The default 5956 is row-oriented. 5957 5958 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5959 5960 Input Parameters: 5961 + mat - the matrix 5962 . op - the option, one of those listed below (and possibly others), 5963 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5964 5965 Options Describing Matrix Structure: 5966 + `MAT_SPD` - symmetric positive definite 5967 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5968 . `MAT_HERMITIAN` - transpose is the complex conjugation 5969 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5970 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5971 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5972 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5973 5974 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5975 do not need to be computed (usually at a high cost) 5976 5977 Options For Use with `MatSetValues()`: 5978 Insert a logically dense subblock, which can be 5979 . `MAT_ROW_ORIENTED` - row-oriented (default) 5980 5981 These options reflect the data you pass in with `MatSetValues()`; it has 5982 nothing to do with how the data is stored internally in the matrix 5983 data structure. 5984 5985 When (re)assembling a matrix, we can restrict the input for 5986 efficiency/debugging purposes. These options include 5987 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5988 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5989 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5990 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5991 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5992 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5993 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5994 performance for very large process counts. 5995 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5996 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5997 functions, instead sending only neighbor messages. 5998 5999 Level: intermediate 6000 6001 Notes: 6002 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 6003 6004 Some options are relevant only for particular matrix types and 6005 are thus ignored by others. Other options are not supported by 6006 certain matrix types and will generate an error message if set. 6007 6008 If using Fortran to compute a matrix, one may need to 6009 use the column-oriented option (or convert to the row-oriented 6010 format). 6011 6012 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6013 that would generate a new entry in the nonzero structure is instead 6014 ignored. Thus, if memory has not already been allocated for this particular 6015 data, then the insertion is ignored. For dense matrices, in which 6016 the entire array is allocated, no entries are ever ignored. 6017 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6018 6019 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6020 that would generate a new entry in the nonzero structure instead produces 6021 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 6022 6023 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6024 that would generate a new entry that has not been preallocated will 6025 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6026 only.) This is a useful flag when debugging matrix memory preallocation. 6027 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6028 6029 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6030 other processors should be dropped, rather than stashed. 6031 This is useful if you know that the "owning" processor is also 6032 always generating the correct matrix entries, so that PETSc need 6033 not transfer duplicate entries generated on another processor. 6034 6035 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6036 searches during matrix assembly. When this flag is set, the hash table 6037 is created during the first matrix assembly. This hash table is 6038 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6039 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6040 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6041 supported by `MATMPIBAIJ` format only. 6042 6043 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6044 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6045 6046 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6047 a zero location in the matrix 6048 6049 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6050 6051 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6052 zero row routines and thus improves performance for very large process counts. 6053 6054 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6055 part of the matrix (since they should match the upper triangular part). 6056 6057 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6058 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6059 with finite difference schemes with non-periodic boundary conditions. 6060 6061 Developer Note: 6062 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6063 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6064 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6065 not changed. 6066 6067 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6068 @*/ 6069 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6070 { 6071 PetscFunctionBegin; 6072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6073 if (op > 0) { 6074 PetscValidLogicalCollectiveEnum(mat, op, 2); 6075 PetscValidLogicalCollectiveBool(mat, flg, 3); 6076 } 6077 6078 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); 6079 6080 switch (op) { 6081 case MAT_FORCE_DIAGONAL_ENTRIES: 6082 mat->force_diagonals = flg; 6083 PetscFunctionReturn(PETSC_SUCCESS); 6084 case MAT_NO_OFF_PROC_ENTRIES: 6085 mat->nooffprocentries = flg; 6086 PetscFunctionReturn(PETSC_SUCCESS); 6087 case MAT_SUBSET_OFF_PROC_ENTRIES: 6088 mat->assembly_subset = flg; 6089 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6090 #if !defined(PETSC_HAVE_MPIUNI) 6091 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6092 #endif 6093 mat->stash.first_assembly_done = PETSC_FALSE; 6094 } 6095 PetscFunctionReturn(PETSC_SUCCESS); 6096 case MAT_NO_OFF_PROC_ZERO_ROWS: 6097 mat->nooffproczerorows = flg; 6098 PetscFunctionReturn(PETSC_SUCCESS); 6099 case MAT_SPD: 6100 if (flg) { 6101 mat->spd = PETSC_BOOL3_TRUE; 6102 mat->symmetric = PETSC_BOOL3_TRUE; 6103 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6104 } else { 6105 mat->spd = PETSC_BOOL3_FALSE; 6106 } 6107 break; 6108 case MAT_SYMMETRIC: 6109 mat->symmetric = PetscBoolToBool3(flg); 6110 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6111 #if !defined(PETSC_USE_COMPLEX) 6112 mat->hermitian = PetscBoolToBool3(flg); 6113 #endif 6114 break; 6115 case MAT_HERMITIAN: 6116 mat->hermitian = PetscBoolToBool3(flg); 6117 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6118 #if !defined(PETSC_USE_COMPLEX) 6119 mat->symmetric = PetscBoolToBool3(flg); 6120 #endif 6121 break; 6122 case MAT_STRUCTURALLY_SYMMETRIC: 6123 mat->structurally_symmetric = PetscBoolToBool3(flg); 6124 break; 6125 case MAT_SYMMETRY_ETERNAL: 6126 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"); 6127 mat->symmetry_eternal = flg; 6128 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6129 break; 6130 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6131 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"); 6132 mat->structural_symmetry_eternal = flg; 6133 break; 6134 case MAT_SPD_ETERNAL: 6135 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"); 6136 mat->spd_eternal = flg; 6137 if (flg) { 6138 mat->structural_symmetry_eternal = PETSC_TRUE; 6139 mat->symmetry_eternal = PETSC_TRUE; 6140 } 6141 break; 6142 case MAT_STRUCTURE_ONLY: 6143 mat->structure_only = flg; 6144 break; 6145 case MAT_SORTED_FULL: 6146 mat->sortedfull = flg; 6147 break; 6148 default: 6149 break; 6150 } 6151 PetscTryTypeMethod(mat, setoption, op, flg); 6152 PetscFunctionReturn(PETSC_SUCCESS); 6153 } 6154 6155 /*@ 6156 MatGetOption - Gets a parameter option that has been set for a matrix. 6157 6158 Logically Collective 6159 6160 Input Parameters: 6161 + mat - the matrix 6162 - op - the option, this only responds to certain options, check the code for which ones 6163 6164 Output Parameter: 6165 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6166 6167 Level: intermediate 6168 6169 Notes: 6170 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6171 6172 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6173 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6174 6175 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6176 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6177 @*/ 6178 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6179 { 6180 PetscFunctionBegin; 6181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6182 PetscValidType(mat, 1); 6183 6184 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); 6185 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()"); 6186 6187 switch (op) { 6188 case MAT_NO_OFF_PROC_ENTRIES: 6189 *flg = mat->nooffprocentries; 6190 break; 6191 case MAT_NO_OFF_PROC_ZERO_ROWS: 6192 *flg = mat->nooffproczerorows; 6193 break; 6194 case MAT_SYMMETRIC: 6195 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6196 break; 6197 case MAT_HERMITIAN: 6198 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6199 break; 6200 case MAT_STRUCTURALLY_SYMMETRIC: 6201 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6202 break; 6203 case MAT_SPD: 6204 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6205 break; 6206 case MAT_SYMMETRY_ETERNAL: 6207 *flg = mat->symmetry_eternal; 6208 break; 6209 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6210 *flg = mat->symmetry_eternal; 6211 break; 6212 default: 6213 break; 6214 } 6215 PetscFunctionReturn(PETSC_SUCCESS); 6216 } 6217 6218 /*@ 6219 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6220 this routine retains the old nonzero structure. 6221 6222 Logically Collective 6223 6224 Input Parameter: 6225 . mat - the matrix 6226 6227 Level: intermediate 6228 6229 Note: 6230 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. 6231 See the Performance chapter of the users manual for information on preallocating matrices. 6232 6233 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6234 @*/ 6235 PetscErrorCode MatZeroEntries(Mat mat) 6236 { 6237 PetscFunctionBegin; 6238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6239 PetscValidType(mat, 1); 6240 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6241 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"); 6242 MatCheckPreallocated(mat, 1); 6243 6244 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6245 PetscUseTypeMethod(mat, zeroentries); 6246 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6247 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6248 PetscFunctionReturn(PETSC_SUCCESS); 6249 } 6250 6251 /*@ 6252 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6253 of a set of rows and columns of a matrix. 6254 6255 Collective 6256 6257 Input Parameters: 6258 + mat - the matrix 6259 . numRows - the number of rows/columns to zero 6260 . rows - the global row indices 6261 . diag - value put in the diagonal of the eliminated rows 6262 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6263 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6264 6265 Level: intermediate 6266 6267 Notes: 6268 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6269 6270 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6271 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 6272 6273 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6274 Krylov method to take advantage of the known solution on the zeroed rows. 6275 6276 For the parallel case, all processes that share the matrix (i.e., 6277 those in the communicator used for matrix creation) MUST call this 6278 routine, regardless of whether any rows being zeroed are owned by 6279 them. 6280 6281 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6282 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 6283 missing. 6284 6285 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6286 list only rows local to itself). 6287 6288 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6289 6290 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6291 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6292 @*/ 6293 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6294 { 6295 PetscFunctionBegin; 6296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6297 PetscValidType(mat, 1); 6298 if (numRows) PetscAssertPointer(rows, 3); 6299 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6300 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6301 MatCheckPreallocated(mat, 1); 6302 6303 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6304 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6305 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6306 PetscFunctionReturn(PETSC_SUCCESS); 6307 } 6308 6309 /*@ 6310 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6311 of a set of rows and columns of a matrix. 6312 6313 Collective 6314 6315 Input Parameters: 6316 + mat - the matrix 6317 . is - the rows to zero 6318 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6319 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6320 - b - optional vector of right-hand side, that will be adjusted by provided solution 6321 6322 Level: intermediate 6323 6324 Note: 6325 See `MatZeroRowsColumns()` for details on how this routine operates. 6326 6327 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6328 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6329 @*/ 6330 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6331 { 6332 PetscInt numRows; 6333 const PetscInt *rows; 6334 6335 PetscFunctionBegin; 6336 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6337 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6338 PetscValidType(mat, 1); 6339 PetscValidType(is, 2); 6340 PetscCall(ISGetLocalSize(is, &numRows)); 6341 PetscCall(ISGetIndices(is, &rows)); 6342 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6343 PetscCall(ISRestoreIndices(is, &rows)); 6344 PetscFunctionReturn(PETSC_SUCCESS); 6345 } 6346 6347 /*@ 6348 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6349 of a set of rows of a matrix. 6350 6351 Collective 6352 6353 Input Parameters: 6354 + mat - the matrix 6355 . numRows - the number of rows to zero 6356 . rows - the global row indices 6357 . diag - value put in the diagonal of the zeroed rows 6358 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6359 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6360 6361 Level: intermediate 6362 6363 Notes: 6364 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6365 6366 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6367 6368 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6369 Krylov method to take advantage of the known solution on the zeroed rows. 6370 6371 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) 6372 from the matrix. 6373 6374 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6375 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6376 formats this does not alter the nonzero structure. 6377 6378 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6379 of the matrix is not changed the values are 6380 merely zeroed. 6381 6382 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6383 formats can optionally remove the main diagonal entry from the 6384 nonzero structure as well, by passing 0.0 as the final argument). 6385 6386 For the parallel case, all processes that share the matrix (i.e., 6387 those in the communicator used for matrix creation) MUST call this 6388 routine, regardless of whether any rows being zeroed are owned by 6389 them. 6390 6391 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6392 list only rows local to itself). 6393 6394 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6395 owns that are to be zeroed. This saves a global synchronization in the implementation. 6396 6397 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6398 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6399 @*/ 6400 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6401 { 6402 PetscFunctionBegin; 6403 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6404 PetscValidType(mat, 1); 6405 if (numRows) PetscAssertPointer(rows, 3); 6406 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6407 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6408 MatCheckPreallocated(mat, 1); 6409 6410 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6411 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6412 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6413 PetscFunctionReturn(PETSC_SUCCESS); 6414 } 6415 6416 /*@ 6417 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6418 of a set of rows of a matrix indicated by an `IS` 6419 6420 Collective 6421 6422 Input Parameters: 6423 + mat - the matrix 6424 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6425 . diag - value put in all diagonals of eliminated rows 6426 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6427 - b - optional vector of right-hand side, that will be adjusted by provided solution 6428 6429 Level: intermediate 6430 6431 Note: 6432 See `MatZeroRows()` for details on how this routine operates. 6433 6434 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6435 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6436 @*/ 6437 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6438 { 6439 PetscInt numRows = 0; 6440 const PetscInt *rows = NULL; 6441 6442 PetscFunctionBegin; 6443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6444 PetscValidType(mat, 1); 6445 if (is) { 6446 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6447 PetscCall(ISGetLocalSize(is, &numRows)); 6448 PetscCall(ISGetIndices(is, &rows)); 6449 } 6450 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6451 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6452 PetscFunctionReturn(PETSC_SUCCESS); 6453 } 6454 6455 /*@ 6456 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6457 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6458 6459 Collective 6460 6461 Input Parameters: 6462 + mat - the matrix 6463 . numRows - the number of rows to remove 6464 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6465 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6466 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6467 - b - optional vector of right-hand side, that will be adjusted by provided solution 6468 6469 Level: intermediate 6470 6471 Notes: 6472 See `MatZeroRows()` for details on how this routine operates. 6473 6474 The grid coordinates are across the entire grid, not just the local portion 6475 6476 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6477 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6478 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6479 `DM_BOUNDARY_PERIODIC` boundary type. 6480 6481 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 6482 a single value per point) you can skip filling those indices. 6483 6484 Fortran Note: 6485 `idxm` and `idxn` should be declared as 6486 $ MatStencil idxm(4, m) 6487 and the values inserted using 6488 .vb 6489 idxm(MatStencil_i, 1) = i 6490 idxm(MatStencil_j, 1) = j 6491 idxm(MatStencil_k, 1) = k 6492 idxm(MatStencil_c, 1) = c 6493 etc 6494 .ve 6495 6496 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6497 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6498 @*/ 6499 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6500 { 6501 PetscInt dim = mat->stencil.dim; 6502 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6503 PetscInt *dims = mat->stencil.dims + 1; 6504 PetscInt *starts = mat->stencil.starts; 6505 PetscInt *dxm = (PetscInt *)rows; 6506 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6507 6508 PetscFunctionBegin; 6509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6510 PetscValidType(mat, 1); 6511 if (numRows) PetscAssertPointer(rows, 3); 6512 6513 PetscCall(PetscMalloc1(numRows, &jdxm)); 6514 for (i = 0; i < numRows; ++i) { 6515 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6516 for (j = 0; j < 3 - sdim; ++j) dxm++; 6517 /* Local index in X dir */ 6518 tmp = *dxm++ - starts[0]; 6519 /* Loop over remaining dimensions */ 6520 for (j = 0; j < dim - 1; ++j) { 6521 /* If nonlocal, set index to be negative */ 6522 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6523 /* Update local index */ 6524 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6525 } 6526 /* Skip component slot if necessary */ 6527 if (mat->stencil.noc) dxm++; 6528 /* Local row number */ 6529 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6530 } 6531 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6532 PetscCall(PetscFree(jdxm)); 6533 PetscFunctionReturn(PETSC_SUCCESS); 6534 } 6535 6536 /*@ 6537 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6538 of a set of rows and columns of a matrix. 6539 6540 Collective 6541 6542 Input Parameters: 6543 + mat - the matrix 6544 . numRows - the number of rows/columns to remove 6545 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6546 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6547 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6548 - b - optional vector of right-hand side, that will be adjusted by provided solution 6549 6550 Level: intermediate 6551 6552 Notes: 6553 See `MatZeroRowsColumns()` for details on how this routine operates. 6554 6555 The grid coordinates are across the entire grid, not just the local portion 6556 6557 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6558 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6559 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6560 `DM_BOUNDARY_PERIODIC` boundary type. 6561 6562 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 6563 a single value per point) you can skip filling those indices. 6564 6565 Fortran Note: 6566 `idxm` and `idxn` should be declared as 6567 $ MatStencil idxm(4, m) 6568 and the values inserted using 6569 .vb 6570 idxm(MatStencil_i, 1) = i 6571 idxm(MatStencil_j, 1) = j 6572 idxm(MatStencil_k, 1) = k 6573 idxm(MatStencil_c, 1) = c 6574 etc 6575 .ve 6576 6577 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6578 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6579 @*/ 6580 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6581 { 6582 PetscInt dim = mat->stencil.dim; 6583 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6584 PetscInt *dims = mat->stencil.dims + 1; 6585 PetscInt *starts = mat->stencil.starts; 6586 PetscInt *dxm = (PetscInt *)rows; 6587 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6588 6589 PetscFunctionBegin; 6590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6591 PetscValidType(mat, 1); 6592 if (numRows) PetscAssertPointer(rows, 3); 6593 6594 PetscCall(PetscMalloc1(numRows, &jdxm)); 6595 for (i = 0; i < numRows; ++i) { 6596 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6597 for (j = 0; j < 3 - sdim; ++j) dxm++; 6598 /* Local index in X dir */ 6599 tmp = *dxm++ - starts[0]; 6600 /* Loop over remaining dimensions */ 6601 for (j = 0; j < dim - 1; ++j) { 6602 /* If nonlocal, set index to be negative */ 6603 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6604 /* Update local index */ 6605 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6606 } 6607 /* Skip component slot if necessary */ 6608 if (mat->stencil.noc) dxm++; 6609 /* Local row number */ 6610 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6611 } 6612 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6613 PetscCall(PetscFree(jdxm)); 6614 PetscFunctionReturn(PETSC_SUCCESS); 6615 } 6616 6617 /*@ 6618 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6619 of a set of rows of a matrix; using local numbering of rows. 6620 6621 Collective 6622 6623 Input Parameters: 6624 + mat - the matrix 6625 . numRows - the number of rows to remove 6626 . rows - the local row indices 6627 . diag - value put in all diagonals of eliminated rows 6628 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6629 - b - optional vector of right-hand side, that will be adjusted by provided solution 6630 6631 Level: intermediate 6632 6633 Notes: 6634 Before calling `MatZeroRowsLocal()`, the user must first set the 6635 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6636 6637 See `MatZeroRows()` for details on how this routine operates. 6638 6639 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6640 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6641 @*/ 6642 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6643 { 6644 PetscFunctionBegin; 6645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6646 PetscValidType(mat, 1); 6647 if (numRows) PetscAssertPointer(rows, 3); 6648 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6649 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6650 MatCheckPreallocated(mat, 1); 6651 6652 if (mat->ops->zerorowslocal) { 6653 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6654 } else { 6655 IS is, newis; 6656 const PetscInt *newRows; 6657 6658 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6659 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6660 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6661 PetscCall(ISGetIndices(newis, &newRows)); 6662 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6663 PetscCall(ISRestoreIndices(newis, &newRows)); 6664 PetscCall(ISDestroy(&newis)); 6665 PetscCall(ISDestroy(&is)); 6666 } 6667 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6668 PetscFunctionReturn(PETSC_SUCCESS); 6669 } 6670 6671 /*@ 6672 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6673 of a set of rows of a matrix; using local numbering of rows. 6674 6675 Collective 6676 6677 Input Parameters: 6678 + mat - the matrix 6679 . is - index set of rows to remove 6680 . diag - value put in all diagonals of eliminated rows 6681 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6682 - b - optional vector of right-hand side, that will be adjusted by provided solution 6683 6684 Level: intermediate 6685 6686 Notes: 6687 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6688 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6689 6690 See `MatZeroRows()` for details on how this routine operates. 6691 6692 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6693 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6694 @*/ 6695 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6696 { 6697 PetscInt numRows; 6698 const PetscInt *rows; 6699 6700 PetscFunctionBegin; 6701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6702 PetscValidType(mat, 1); 6703 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6704 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6705 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6706 MatCheckPreallocated(mat, 1); 6707 6708 PetscCall(ISGetLocalSize(is, &numRows)); 6709 PetscCall(ISGetIndices(is, &rows)); 6710 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6711 PetscCall(ISRestoreIndices(is, &rows)); 6712 PetscFunctionReturn(PETSC_SUCCESS); 6713 } 6714 6715 /*@ 6716 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6717 of a set of rows and columns of a matrix; using local numbering of rows. 6718 6719 Collective 6720 6721 Input Parameters: 6722 + mat - the matrix 6723 . numRows - the number of rows to remove 6724 . rows - the global row indices 6725 . diag - value put in all diagonals of eliminated rows 6726 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6727 - b - optional vector of right-hand side, that will be adjusted by provided solution 6728 6729 Level: intermediate 6730 6731 Notes: 6732 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6733 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6734 6735 See `MatZeroRowsColumns()` for details on how this routine operates. 6736 6737 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6738 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6739 @*/ 6740 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6741 { 6742 IS is, newis; 6743 const PetscInt *newRows; 6744 6745 PetscFunctionBegin; 6746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6747 PetscValidType(mat, 1); 6748 if (numRows) PetscAssertPointer(rows, 3); 6749 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6750 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6751 MatCheckPreallocated(mat, 1); 6752 6753 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6754 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6755 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6756 PetscCall(ISGetIndices(newis, &newRows)); 6757 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6758 PetscCall(ISRestoreIndices(newis, &newRows)); 6759 PetscCall(ISDestroy(&newis)); 6760 PetscCall(ISDestroy(&is)); 6761 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6762 PetscFunctionReturn(PETSC_SUCCESS); 6763 } 6764 6765 /*@ 6766 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6767 of a set of rows and columns of a matrix; using local numbering of rows. 6768 6769 Collective 6770 6771 Input Parameters: 6772 + mat - the matrix 6773 . is - index set of rows to remove 6774 . diag - value put in all diagonals of eliminated rows 6775 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6776 - b - optional vector of right-hand side, that will be adjusted by provided solution 6777 6778 Level: intermediate 6779 6780 Notes: 6781 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6782 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6783 6784 See `MatZeroRowsColumns()` for details on how this routine operates. 6785 6786 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6787 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6788 @*/ 6789 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6790 { 6791 PetscInt numRows; 6792 const PetscInt *rows; 6793 6794 PetscFunctionBegin; 6795 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6796 PetscValidType(mat, 1); 6797 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6798 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6799 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6800 MatCheckPreallocated(mat, 1); 6801 6802 PetscCall(ISGetLocalSize(is, &numRows)); 6803 PetscCall(ISGetIndices(is, &rows)); 6804 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6805 PetscCall(ISRestoreIndices(is, &rows)); 6806 PetscFunctionReturn(PETSC_SUCCESS); 6807 } 6808 6809 /*@ 6810 MatGetSize - Returns the numbers of rows and columns in a matrix. 6811 6812 Not Collective 6813 6814 Input Parameter: 6815 . mat - the matrix 6816 6817 Output Parameters: 6818 + m - the number of global rows 6819 - n - the number of global columns 6820 6821 Level: beginner 6822 6823 Note: 6824 Both output parameters can be `NULL` on input. 6825 6826 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6827 @*/ 6828 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6829 { 6830 PetscFunctionBegin; 6831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6832 if (m) *m = mat->rmap->N; 6833 if (n) *n = mat->cmap->N; 6834 PetscFunctionReturn(PETSC_SUCCESS); 6835 } 6836 6837 /*@ 6838 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6839 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6840 6841 Not Collective 6842 6843 Input Parameter: 6844 . mat - the matrix 6845 6846 Output Parameters: 6847 + m - the number of local rows, use `NULL` to not obtain this value 6848 - n - the number of local columns, use `NULL` to not obtain this value 6849 6850 Level: beginner 6851 6852 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6853 @*/ 6854 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6855 { 6856 PetscFunctionBegin; 6857 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6858 if (m) PetscAssertPointer(m, 2); 6859 if (n) PetscAssertPointer(n, 3); 6860 if (m) *m = mat->rmap->n; 6861 if (n) *n = mat->cmap->n; 6862 PetscFunctionReturn(PETSC_SUCCESS); 6863 } 6864 6865 /*@ 6866 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6867 vector one multiplies this matrix by that are owned by this processor. 6868 6869 Not Collective, unless matrix has not been allocated, then collective 6870 6871 Input Parameter: 6872 . mat - the matrix 6873 6874 Output Parameters: 6875 + m - the global index of the first local column, use `NULL` to not obtain this value 6876 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6877 6878 Level: developer 6879 6880 Notes: 6881 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6882 6883 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6884 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6885 6886 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6887 the local values in the matrix. 6888 6889 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6890 Layouts](sec_matlayout) for details on matrix layouts. 6891 6892 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6893 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6894 @*/ 6895 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6896 { 6897 PetscFunctionBegin; 6898 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6899 PetscValidType(mat, 1); 6900 if (m) PetscAssertPointer(m, 2); 6901 if (n) PetscAssertPointer(n, 3); 6902 MatCheckPreallocated(mat, 1); 6903 if (m) *m = mat->cmap->rstart; 6904 if (n) *n = mat->cmap->rend; 6905 PetscFunctionReturn(PETSC_SUCCESS); 6906 } 6907 6908 /*@ 6909 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6910 this MPI process. 6911 6912 Not Collective 6913 6914 Input Parameter: 6915 . mat - the matrix 6916 6917 Output Parameters: 6918 + m - the global index of the first local row, use `NULL` to not obtain this value 6919 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6920 6921 Level: beginner 6922 6923 Notes: 6924 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6925 6926 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6927 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6928 6929 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6930 the local values in the matrix. 6931 6932 The high argument is one more than the last element stored locally. 6933 6934 For all matrices it returns the range of matrix rows associated with rows of a vector that 6935 would contain the result of a matrix vector product with this matrix. See [Matrix 6936 Layouts](sec_matlayout) for details on matrix layouts. 6937 6938 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6939 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6940 @*/ 6941 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6942 { 6943 PetscFunctionBegin; 6944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6945 PetscValidType(mat, 1); 6946 if (m) PetscAssertPointer(m, 2); 6947 if (n) PetscAssertPointer(n, 3); 6948 MatCheckPreallocated(mat, 1); 6949 if (m) *m = mat->rmap->rstart; 6950 if (n) *n = mat->rmap->rend; 6951 PetscFunctionReturn(PETSC_SUCCESS); 6952 } 6953 6954 /*@C 6955 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6956 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6957 6958 Not Collective, unless matrix has not been allocated 6959 6960 Input Parameter: 6961 . mat - the matrix 6962 6963 Output Parameter: 6964 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6965 where `size` is the number of MPI processes used by `mat` 6966 6967 Level: beginner 6968 6969 Notes: 6970 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6971 6972 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6973 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6974 6975 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6976 the local values in the matrix. 6977 6978 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6979 would contain the result of a matrix vector product with this matrix. See [Matrix 6980 Layouts](sec_matlayout) for details on matrix layouts. 6981 6982 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6983 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6984 `DMDAGetGhostCorners()`, `DM` 6985 @*/ 6986 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6987 { 6988 PetscFunctionBegin; 6989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6990 PetscValidType(mat, 1); 6991 MatCheckPreallocated(mat, 1); 6992 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6993 PetscFunctionReturn(PETSC_SUCCESS); 6994 } 6995 6996 /*@C 6997 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6998 vector one multiplies this vector by that are owned by each processor. 6999 7000 Not Collective, unless matrix has not been allocated 7001 7002 Input Parameter: 7003 . mat - the matrix 7004 7005 Output Parameter: 7006 . ranges - start of each processors portion plus one more than the total length at the end 7007 7008 Level: beginner 7009 7010 Notes: 7011 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7012 7013 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7014 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7015 7016 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7017 the local values in the matrix. 7018 7019 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7020 Layouts](sec_matlayout) for details on matrix layouts. 7021 7022 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7023 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7024 `DMDAGetGhostCorners()`, `DM` 7025 @*/ 7026 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7027 { 7028 PetscFunctionBegin; 7029 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7030 PetscValidType(mat, 1); 7031 MatCheckPreallocated(mat, 1); 7032 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7033 PetscFunctionReturn(PETSC_SUCCESS); 7034 } 7035 7036 /*@ 7037 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7038 7039 Not Collective 7040 7041 Input Parameter: 7042 . A - matrix 7043 7044 Output Parameters: 7045 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7046 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7047 7048 Level: intermediate 7049 7050 Note: 7051 You should call `ISDestroy()` on the returned `IS` 7052 7053 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7054 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7055 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7056 details on matrix layouts. 7057 7058 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7059 @*/ 7060 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7061 { 7062 PetscErrorCode (*f)(Mat, IS *, IS *); 7063 7064 PetscFunctionBegin; 7065 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7066 PetscValidType(A, 1); 7067 MatCheckPreallocated(A, 1); 7068 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7069 if (f) { 7070 PetscCall((*f)(A, rows, cols)); 7071 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7072 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7073 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7074 } 7075 PetscFunctionReturn(PETSC_SUCCESS); 7076 } 7077 7078 /*@ 7079 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7080 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7081 to complete the factorization. 7082 7083 Collective 7084 7085 Input Parameters: 7086 + fact - the factorized matrix obtained with `MatGetFactor()` 7087 . mat - the matrix 7088 . row - row permutation 7089 . col - column permutation 7090 - info - structure containing 7091 .vb 7092 levels - number of levels of fill. 7093 expected fill - as ratio of original fill. 7094 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7095 missing diagonal entries) 7096 .ve 7097 7098 Level: developer 7099 7100 Notes: 7101 See [Matrix Factorization](sec_matfactor) for additional information. 7102 7103 Most users should employ the `KSP` interface for linear solvers 7104 instead of working directly with matrix algebra routines such as this. 7105 See, e.g., `KSPCreate()`. 7106 7107 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7108 7109 Developer Note: 7110 The Fortran interface is not autogenerated as the 7111 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7112 7113 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7114 `MatGetOrdering()`, `MatFactorInfo` 7115 @*/ 7116 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7117 { 7118 PetscFunctionBegin; 7119 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7120 PetscValidType(mat, 2); 7121 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7122 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7123 PetscAssertPointer(info, 5); 7124 PetscAssertPointer(fact, 1); 7125 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7126 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7127 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7128 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7129 MatCheckPreallocated(mat, 2); 7130 7131 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7132 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7133 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7134 PetscFunctionReturn(PETSC_SUCCESS); 7135 } 7136 7137 /*@ 7138 MatICCFactorSymbolic - Performs symbolic incomplete 7139 Cholesky factorization for a symmetric matrix. Use 7140 `MatCholeskyFactorNumeric()` to complete the factorization. 7141 7142 Collective 7143 7144 Input Parameters: 7145 + fact - the factorized matrix obtained with `MatGetFactor()` 7146 . mat - the matrix to be factored 7147 . perm - row and column permutation 7148 - info - structure containing 7149 .vb 7150 levels - number of levels of fill. 7151 expected fill - as ratio of original fill. 7152 .ve 7153 7154 Level: developer 7155 7156 Notes: 7157 Most users should employ the `KSP` interface for linear solvers 7158 instead of working directly with matrix algebra routines such as this. 7159 See, e.g., `KSPCreate()`. 7160 7161 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7162 7163 Developer Note: 7164 The Fortran interface is not autogenerated as the 7165 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7166 7167 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7168 @*/ 7169 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7170 { 7171 PetscFunctionBegin; 7172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7173 PetscValidType(mat, 2); 7174 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7175 PetscAssertPointer(info, 4); 7176 PetscAssertPointer(fact, 1); 7177 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7178 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7179 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7180 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7181 MatCheckPreallocated(mat, 2); 7182 7183 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7184 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7185 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7186 PetscFunctionReturn(PETSC_SUCCESS); 7187 } 7188 7189 /*@C 7190 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7191 points to an array of valid matrices, they may be reused to store the new 7192 submatrices. 7193 7194 Collective 7195 7196 Input Parameters: 7197 + mat - the matrix 7198 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7199 . irow - index set of rows to extract 7200 . icol - index set of columns to extract 7201 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7202 7203 Output Parameter: 7204 . submat - the array of submatrices 7205 7206 Level: advanced 7207 7208 Notes: 7209 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7210 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7211 to extract a parallel submatrix. 7212 7213 Some matrix types place restrictions on the row and column 7214 indices, such as that they be sorted or that they be equal to each other. 7215 7216 The index sets may not have duplicate entries. 7217 7218 When extracting submatrices from a parallel matrix, each processor can 7219 form a different submatrix by setting the rows and columns of its 7220 individual index sets according to the local submatrix desired. 7221 7222 When finished using the submatrices, the user should destroy 7223 them with `MatDestroySubMatrices()`. 7224 7225 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7226 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7227 7228 This routine creates the matrices in submat; you should NOT create them before 7229 calling it. It also allocates the array of matrix pointers submat. 7230 7231 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7232 request one row/column in a block, they must request all rows/columns that are in 7233 that block. For example, if the block size is 2 you cannot request just row 0 and 7234 column 0. 7235 7236 Fortran Note: 7237 .vb 7238 Mat, pointer :: submat(:) 7239 .ve 7240 7241 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7242 @*/ 7243 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7244 { 7245 PetscInt i; 7246 PetscBool eq; 7247 7248 PetscFunctionBegin; 7249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7250 PetscValidType(mat, 1); 7251 if (n) { 7252 PetscAssertPointer(irow, 3); 7253 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7254 PetscAssertPointer(icol, 4); 7255 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7256 } 7257 PetscAssertPointer(submat, 6); 7258 if (n && scall == MAT_REUSE_MATRIX) { 7259 PetscAssertPointer(*submat, 6); 7260 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7261 } 7262 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7263 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7264 MatCheckPreallocated(mat, 1); 7265 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7266 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7267 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7268 for (i = 0; i < n; i++) { 7269 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7270 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7271 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7272 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7273 if (mat->boundtocpu && mat->bindingpropagates) { 7274 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7275 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7276 } 7277 #endif 7278 } 7279 PetscFunctionReturn(PETSC_SUCCESS); 7280 } 7281 7282 /*@C 7283 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7284 7285 Collective 7286 7287 Input Parameters: 7288 + mat - the matrix 7289 . n - the number of submatrixes to be extracted 7290 . irow - index set of rows to extract 7291 . icol - index set of columns to extract 7292 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7293 7294 Output Parameter: 7295 . submat - the array of submatrices 7296 7297 Level: advanced 7298 7299 Note: 7300 This is used by `PCGASM` 7301 7302 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7303 @*/ 7304 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7305 { 7306 PetscInt i; 7307 PetscBool eq; 7308 7309 PetscFunctionBegin; 7310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7311 PetscValidType(mat, 1); 7312 if (n) { 7313 PetscAssertPointer(irow, 3); 7314 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7315 PetscAssertPointer(icol, 4); 7316 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7317 } 7318 PetscAssertPointer(submat, 6); 7319 if (n && scall == MAT_REUSE_MATRIX) { 7320 PetscAssertPointer(*submat, 6); 7321 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7322 } 7323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7324 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7325 MatCheckPreallocated(mat, 1); 7326 7327 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7328 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7329 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7330 for (i = 0; i < n; i++) { 7331 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7332 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7333 } 7334 PetscFunctionReturn(PETSC_SUCCESS); 7335 } 7336 7337 /*@C 7338 MatDestroyMatrices - Destroys an array of matrices 7339 7340 Collective 7341 7342 Input Parameters: 7343 + n - the number of local matrices 7344 - mat - the matrices (this is a pointer to the array of matrices) 7345 7346 Level: advanced 7347 7348 Notes: 7349 Frees not only the matrices, but also the array that contains the matrices 7350 7351 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7352 7353 Fortran Note: 7354 Does not free the `mat` array. 7355 7356 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7357 @*/ 7358 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7359 { 7360 PetscInt i; 7361 7362 PetscFunctionBegin; 7363 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7364 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7365 PetscAssertPointer(mat, 2); 7366 7367 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7368 7369 /* memory is allocated even if n = 0 */ 7370 PetscCall(PetscFree(*mat)); 7371 PetscFunctionReturn(PETSC_SUCCESS); 7372 } 7373 7374 /*@C 7375 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7376 7377 Collective 7378 7379 Input Parameters: 7380 + n - the number of local matrices 7381 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7382 7383 Level: advanced 7384 7385 Note: 7386 Frees not only the matrices, but also the array that contains the matrices 7387 7388 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7389 @*/ 7390 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7391 { 7392 Mat mat0; 7393 7394 PetscFunctionBegin; 7395 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7396 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7397 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7398 PetscAssertPointer(mat, 2); 7399 7400 mat0 = (*mat)[0]; 7401 if (mat0 && mat0->ops->destroysubmatrices) { 7402 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7403 } else { 7404 PetscCall(MatDestroyMatrices(n, mat)); 7405 } 7406 PetscFunctionReturn(PETSC_SUCCESS); 7407 } 7408 7409 /*@ 7410 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7411 7412 Collective 7413 7414 Input Parameter: 7415 . mat - the matrix 7416 7417 Output Parameter: 7418 . matstruct - the sequential matrix with the nonzero structure of `mat` 7419 7420 Level: developer 7421 7422 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7423 @*/ 7424 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7425 { 7426 PetscFunctionBegin; 7427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7428 PetscAssertPointer(matstruct, 2); 7429 7430 PetscValidType(mat, 1); 7431 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7432 MatCheckPreallocated(mat, 1); 7433 7434 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7435 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7436 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7437 PetscFunctionReturn(PETSC_SUCCESS); 7438 } 7439 7440 /*@C 7441 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7442 7443 Collective 7444 7445 Input Parameter: 7446 . mat - the matrix 7447 7448 Level: advanced 7449 7450 Note: 7451 This is not needed, one can just call `MatDestroy()` 7452 7453 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7454 @*/ 7455 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7456 { 7457 PetscFunctionBegin; 7458 PetscAssertPointer(mat, 1); 7459 PetscCall(MatDestroy(mat)); 7460 PetscFunctionReturn(PETSC_SUCCESS); 7461 } 7462 7463 /*@ 7464 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7465 replaces the index sets by larger ones that represent submatrices with 7466 additional overlap. 7467 7468 Collective 7469 7470 Input Parameters: 7471 + mat - the matrix 7472 . n - the number of index sets 7473 . is - the array of index sets (these index sets will changed during the call) 7474 - ov - the additional overlap requested 7475 7476 Options Database Key: 7477 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7478 7479 Level: developer 7480 7481 Note: 7482 The computed overlap preserves the matrix block sizes when the blocks are square. 7483 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7484 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7485 7486 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7487 @*/ 7488 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7489 { 7490 PetscInt i, bs, cbs; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7494 PetscValidType(mat, 1); 7495 PetscValidLogicalCollectiveInt(mat, n, 2); 7496 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7497 if (n) { 7498 PetscAssertPointer(is, 3); 7499 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7500 } 7501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7503 MatCheckPreallocated(mat, 1); 7504 7505 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7506 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7507 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7508 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7509 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7510 if (bs == cbs) { 7511 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7512 } 7513 PetscFunctionReturn(PETSC_SUCCESS); 7514 } 7515 7516 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7517 7518 /*@ 7519 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7520 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7521 additional overlap. 7522 7523 Collective 7524 7525 Input Parameters: 7526 + mat - the matrix 7527 . n - the number of index sets 7528 . is - the array of index sets (these index sets will changed during the call) 7529 - ov - the additional overlap requested 7530 7531 ` Options Database Key: 7532 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7533 7534 Level: developer 7535 7536 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7537 @*/ 7538 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7539 { 7540 PetscInt i; 7541 7542 PetscFunctionBegin; 7543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7544 PetscValidType(mat, 1); 7545 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7546 if (n) { 7547 PetscAssertPointer(is, 3); 7548 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7549 } 7550 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7551 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7552 MatCheckPreallocated(mat, 1); 7553 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7554 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7555 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7556 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7557 PetscFunctionReturn(PETSC_SUCCESS); 7558 } 7559 7560 /*@ 7561 MatGetBlockSize - Returns the matrix block size. 7562 7563 Not Collective 7564 7565 Input Parameter: 7566 . mat - the matrix 7567 7568 Output Parameter: 7569 . bs - block size 7570 7571 Level: intermediate 7572 7573 Notes: 7574 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7575 7576 If the block size has not been set yet this routine returns 1. 7577 7578 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7579 @*/ 7580 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7581 { 7582 PetscFunctionBegin; 7583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7584 PetscAssertPointer(bs, 2); 7585 *bs = PetscAbs(mat->rmap->bs); 7586 PetscFunctionReturn(PETSC_SUCCESS); 7587 } 7588 7589 /*@ 7590 MatGetBlockSizes - Returns the matrix block row and column sizes. 7591 7592 Not Collective 7593 7594 Input Parameter: 7595 . mat - the matrix 7596 7597 Output Parameters: 7598 + rbs - row block size 7599 - cbs - column block size 7600 7601 Level: intermediate 7602 7603 Notes: 7604 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7605 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7606 7607 If a block size has not been set yet this routine returns 1. 7608 7609 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7610 @*/ 7611 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7612 { 7613 PetscFunctionBegin; 7614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7615 if (rbs) PetscAssertPointer(rbs, 2); 7616 if (cbs) PetscAssertPointer(cbs, 3); 7617 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7618 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7619 PetscFunctionReturn(PETSC_SUCCESS); 7620 } 7621 7622 /*@ 7623 MatSetBlockSize - Sets the matrix block size. 7624 7625 Logically Collective 7626 7627 Input Parameters: 7628 + mat - the matrix 7629 - bs - block size 7630 7631 Level: intermediate 7632 7633 Notes: 7634 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7635 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7636 7637 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7638 is compatible with the matrix local sizes. 7639 7640 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7641 @*/ 7642 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7643 { 7644 PetscFunctionBegin; 7645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7646 PetscValidLogicalCollectiveInt(mat, bs, 2); 7647 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7648 PetscFunctionReturn(PETSC_SUCCESS); 7649 } 7650 7651 typedef struct { 7652 PetscInt n; 7653 IS *is; 7654 Mat *mat; 7655 PetscObjectState nonzerostate; 7656 Mat C; 7657 } EnvelopeData; 7658 7659 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7660 { 7661 EnvelopeData *edata = (EnvelopeData *)*ptr; 7662 7663 PetscFunctionBegin; 7664 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7665 PetscCall(PetscFree(edata->is)); 7666 PetscCall(PetscFree(edata)); 7667 PetscFunctionReturn(PETSC_SUCCESS); 7668 } 7669 7670 /*@ 7671 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7672 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7673 7674 Collective 7675 7676 Input Parameter: 7677 . mat - the matrix 7678 7679 Level: intermediate 7680 7681 Notes: 7682 There can be zeros within the blocks 7683 7684 The blocks can overlap between processes, including laying on more than two processes 7685 7686 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7687 @*/ 7688 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7689 { 7690 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7691 PetscInt *diag, *odiag, sc; 7692 VecScatter scatter; 7693 PetscScalar *seqv; 7694 const PetscScalar *parv; 7695 const PetscInt *ia, *ja; 7696 PetscBool set, flag, done; 7697 Mat AA = mat, A; 7698 MPI_Comm comm; 7699 PetscMPIInt rank, size, tag; 7700 MPI_Status status; 7701 PetscContainer container; 7702 EnvelopeData *edata; 7703 Vec seq, par; 7704 IS isglobal; 7705 7706 PetscFunctionBegin; 7707 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7708 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7709 if (!set || !flag) { 7710 /* TODO: only needs nonzero structure of transpose */ 7711 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7712 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7713 } 7714 PetscCall(MatAIJGetLocalMat(AA, &A)); 7715 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7716 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7717 7718 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7719 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7720 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7721 PetscCallMPI(MPI_Comm_size(comm, &size)); 7722 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7723 7724 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7725 7726 if (rank > 0) { 7727 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7728 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7729 } 7730 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7731 for (i = 0; i < n; i++) { 7732 env = PetscMax(env, ja[ia[i + 1] - 1]); 7733 II = rstart + i; 7734 if (env == II) { 7735 starts[lblocks] = tbs; 7736 sizes[lblocks++] = 1 + II - tbs; 7737 tbs = 1 + II; 7738 } 7739 } 7740 if (rank < size - 1) { 7741 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7742 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7743 } 7744 7745 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7746 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7747 PetscCall(MatDestroy(&A)); 7748 7749 PetscCall(PetscNew(&edata)); 7750 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7751 edata->n = lblocks; 7752 /* create IS needed for extracting blocks from the original matrix */ 7753 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7754 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7755 7756 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7757 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7758 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7759 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7760 PetscCall(MatSetType(edata->C, MATAIJ)); 7761 7762 /* Communicate the start and end of each row, from each block to the correct rank */ 7763 /* TODO: Use PetscSF instead of VecScatter */ 7764 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7765 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7766 PetscCall(VecGetArrayWrite(seq, &seqv)); 7767 for (PetscInt i = 0; i < lblocks; i++) { 7768 for (PetscInt j = 0; j < sizes[i]; j++) { 7769 seqv[cnt] = starts[i]; 7770 seqv[cnt + 1] = starts[i] + sizes[i]; 7771 cnt += 2; 7772 } 7773 } 7774 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7775 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7776 sc -= cnt; 7777 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7778 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7779 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7780 PetscCall(ISDestroy(&isglobal)); 7781 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7782 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7783 PetscCall(VecScatterDestroy(&scatter)); 7784 PetscCall(VecDestroy(&seq)); 7785 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7786 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7787 PetscCall(VecGetArrayRead(par, &parv)); 7788 cnt = 0; 7789 PetscCall(MatGetSize(mat, NULL, &n)); 7790 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7791 PetscInt start, end, d = 0, od = 0; 7792 7793 start = (PetscInt)PetscRealPart(parv[cnt]); 7794 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7795 cnt += 2; 7796 7797 if (start < cstart) { 7798 od += cstart - start + n - cend; 7799 d += cend - cstart; 7800 } else if (start < cend) { 7801 od += n - cend; 7802 d += cend - start; 7803 } else od += n - start; 7804 if (end <= cstart) { 7805 od -= cstart - end + n - cend; 7806 d -= cend - cstart; 7807 } else if (end < cend) { 7808 od -= n - cend; 7809 d -= cend - end; 7810 } else od -= n - end; 7811 7812 odiag[i] = od; 7813 diag[i] = d; 7814 } 7815 PetscCall(VecRestoreArrayRead(par, &parv)); 7816 PetscCall(VecDestroy(&par)); 7817 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7818 PetscCall(PetscFree2(diag, odiag)); 7819 PetscCall(PetscFree2(sizes, starts)); 7820 7821 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7822 PetscCall(PetscContainerSetPointer(container, edata)); 7823 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7824 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7825 PetscCall(PetscObjectDereference((PetscObject)container)); 7826 PetscFunctionReturn(PETSC_SUCCESS); 7827 } 7828 7829 /*@ 7830 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7831 7832 Collective 7833 7834 Input Parameters: 7835 + A - the matrix 7836 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7837 7838 Output Parameter: 7839 . C - matrix with inverted block diagonal of `A` 7840 7841 Level: advanced 7842 7843 Note: 7844 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7845 7846 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7847 @*/ 7848 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7849 { 7850 PetscContainer container; 7851 EnvelopeData *edata; 7852 PetscObjectState nonzerostate; 7853 7854 PetscFunctionBegin; 7855 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7856 if (!container) { 7857 PetscCall(MatComputeVariableBlockEnvelope(A)); 7858 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7859 } 7860 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7861 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7862 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7863 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7864 7865 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7866 *C = edata->C; 7867 7868 for (PetscInt i = 0; i < edata->n; i++) { 7869 Mat D; 7870 PetscScalar *dvalues; 7871 7872 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7873 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7874 PetscCall(MatSeqDenseInvert(D)); 7875 PetscCall(MatDenseGetArray(D, &dvalues)); 7876 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7877 PetscCall(MatDestroy(&D)); 7878 } 7879 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7880 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7881 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7882 PetscFunctionReturn(PETSC_SUCCESS); 7883 } 7884 7885 /*@ 7886 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7887 7888 Not Collective 7889 7890 Input Parameters: 7891 + mat - the matrix 7892 . nblocks - the number of blocks on this process, each block can only exist on a single process 7893 - bsizes - the block sizes 7894 7895 Level: intermediate 7896 7897 Notes: 7898 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7899 7900 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. 7901 7902 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7903 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7904 @*/ 7905 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7906 { 7907 PetscInt ncnt = 0, nlocal; 7908 7909 PetscFunctionBegin; 7910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7911 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7912 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); 7913 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7914 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); 7915 PetscCall(PetscFree(mat->bsizes)); 7916 mat->nblocks = nblocks; 7917 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7918 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7919 PetscFunctionReturn(PETSC_SUCCESS); 7920 } 7921 7922 /*@C 7923 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7924 7925 Not Collective; No Fortran Support 7926 7927 Input Parameter: 7928 . mat - the matrix 7929 7930 Output Parameters: 7931 + nblocks - the number of blocks on this process 7932 - bsizes - the block sizes 7933 7934 Level: intermediate 7935 7936 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7937 @*/ 7938 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7939 { 7940 PetscFunctionBegin; 7941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7942 if (nblocks) *nblocks = mat->nblocks; 7943 if (bsizes) *bsizes = mat->bsizes; 7944 PetscFunctionReturn(PETSC_SUCCESS); 7945 } 7946 7947 /*@ 7948 MatSetBlockSizes - Sets the matrix block row and column sizes. 7949 7950 Logically Collective 7951 7952 Input Parameters: 7953 + mat - the matrix 7954 . rbs - row block size 7955 - cbs - column block size 7956 7957 Level: intermediate 7958 7959 Notes: 7960 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7961 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7962 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7963 7964 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7965 are compatible with the matrix local sizes. 7966 7967 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7968 7969 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7970 @*/ 7971 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7972 { 7973 PetscFunctionBegin; 7974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7975 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7976 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7977 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7978 if (mat->rmap->refcnt) { 7979 ISLocalToGlobalMapping l2g = NULL; 7980 PetscLayout nmap = NULL; 7981 7982 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7983 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7984 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7985 mat->rmap = nmap; 7986 mat->rmap->mapping = l2g; 7987 } 7988 if (mat->cmap->refcnt) { 7989 ISLocalToGlobalMapping l2g = NULL; 7990 PetscLayout nmap = NULL; 7991 7992 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7993 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7994 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7995 mat->cmap = nmap; 7996 mat->cmap->mapping = l2g; 7997 } 7998 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7999 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8000 PetscFunctionReturn(PETSC_SUCCESS); 8001 } 8002 8003 /*@ 8004 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8005 8006 Logically Collective 8007 8008 Input Parameters: 8009 + mat - the matrix 8010 . fromRow - matrix from which to copy row block size 8011 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8012 8013 Level: developer 8014 8015 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8016 @*/ 8017 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8018 { 8019 PetscFunctionBegin; 8020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8021 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8022 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8023 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8024 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8025 PetscFunctionReturn(PETSC_SUCCESS); 8026 } 8027 8028 /*@ 8029 MatResidual - Default routine to calculate the residual r = b - Ax 8030 8031 Collective 8032 8033 Input Parameters: 8034 + mat - the matrix 8035 . b - the right-hand-side 8036 - x - the approximate solution 8037 8038 Output Parameter: 8039 . r - location to store the residual 8040 8041 Level: developer 8042 8043 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8044 @*/ 8045 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8046 { 8047 PetscFunctionBegin; 8048 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8049 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8050 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8051 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8052 PetscValidType(mat, 1); 8053 MatCheckPreallocated(mat, 1); 8054 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8055 if (!mat->ops->residual) { 8056 PetscCall(MatMult(mat, x, r)); 8057 PetscCall(VecAYPX(r, -1.0, b)); 8058 } else { 8059 PetscUseTypeMethod(mat, residual, b, x, r); 8060 } 8061 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8062 PetscFunctionReturn(PETSC_SUCCESS); 8063 } 8064 8065 /*@C 8066 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8067 8068 Collective 8069 8070 Input Parameters: 8071 + mat - the matrix 8072 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8073 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8074 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8075 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8076 always used. 8077 8078 Output Parameters: 8079 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8080 . 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 8081 . ja - the column indices, use `NULL` if not needed 8082 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8083 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8084 8085 Level: developer 8086 8087 Notes: 8088 You CANNOT change any of the ia[] or ja[] values. 8089 8090 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8091 8092 Fortran Notes: 8093 Use 8094 .vb 8095 PetscInt, pointer :: ia(:),ja(:) 8096 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8097 ! Access the ith and jth entries via ia(i) and ja(j) 8098 .ve 8099 8100 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8101 @*/ 8102 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8103 { 8104 PetscFunctionBegin; 8105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8106 PetscValidType(mat, 1); 8107 if (n) PetscAssertPointer(n, 5); 8108 if (ia) PetscAssertPointer(ia, 6); 8109 if (ja) PetscAssertPointer(ja, 7); 8110 if (done) PetscAssertPointer(done, 8); 8111 MatCheckPreallocated(mat, 1); 8112 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8113 else { 8114 if (done) *done = PETSC_TRUE; 8115 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8116 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8117 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8118 } 8119 PetscFunctionReturn(PETSC_SUCCESS); 8120 } 8121 8122 /*@C 8123 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8124 8125 Collective 8126 8127 Input Parameters: 8128 + mat - the matrix 8129 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8130 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8131 symmetrized 8132 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8133 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8134 always used. 8135 . n - number of columns in the (possibly compressed) matrix 8136 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8137 - ja - the row indices 8138 8139 Output Parameter: 8140 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8141 8142 Level: developer 8143 8144 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8145 @*/ 8146 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8147 { 8148 PetscFunctionBegin; 8149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8150 PetscValidType(mat, 1); 8151 PetscAssertPointer(n, 5); 8152 if (ia) PetscAssertPointer(ia, 6); 8153 if (ja) PetscAssertPointer(ja, 7); 8154 PetscAssertPointer(done, 8); 8155 MatCheckPreallocated(mat, 1); 8156 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8157 else { 8158 *done = PETSC_TRUE; 8159 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8160 } 8161 PetscFunctionReturn(PETSC_SUCCESS); 8162 } 8163 8164 /*@C 8165 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8166 8167 Collective 8168 8169 Input Parameters: 8170 + mat - the matrix 8171 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8172 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8173 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8174 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8175 always used. 8176 . n - size of (possibly compressed) matrix 8177 . ia - the row pointers 8178 - ja - the column indices 8179 8180 Output Parameter: 8181 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8182 8183 Level: developer 8184 8185 Note: 8186 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8187 us of the array after it has been restored. If you pass `NULL`, it will 8188 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8189 8190 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8191 @*/ 8192 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8193 { 8194 PetscFunctionBegin; 8195 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8196 PetscValidType(mat, 1); 8197 if (ia) PetscAssertPointer(ia, 6); 8198 if (ja) PetscAssertPointer(ja, 7); 8199 if (done) PetscAssertPointer(done, 8); 8200 MatCheckPreallocated(mat, 1); 8201 8202 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8203 else { 8204 if (done) *done = PETSC_TRUE; 8205 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8206 if (n) *n = 0; 8207 if (ia) *ia = NULL; 8208 if (ja) *ja = NULL; 8209 } 8210 PetscFunctionReturn(PETSC_SUCCESS); 8211 } 8212 8213 /*@C 8214 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8215 8216 Collective 8217 8218 Input Parameters: 8219 + mat - the matrix 8220 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8221 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8222 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8223 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8224 always used. 8225 8226 Output Parameters: 8227 + n - size of (possibly compressed) matrix 8228 . ia - the column pointers 8229 . ja - the row indices 8230 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8231 8232 Level: developer 8233 8234 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8235 @*/ 8236 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8237 { 8238 PetscFunctionBegin; 8239 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8240 PetscValidType(mat, 1); 8241 if (ia) PetscAssertPointer(ia, 6); 8242 if (ja) PetscAssertPointer(ja, 7); 8243 PetscAssertPointer(done, 8); 8244 MatCheckPreallocated(mat, 1); 8245 8246 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8247 else { 8248 *done = PETSC_TRUE; 8249 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8250 if (n) *n = 0; 8251 if (ia) *ia = NULL; 8252 if (ja) *ja = NULL; 8253 } 8254 PetscFunctionReturn(PETSC_SUCCESS); 8255 } 8256 8257 /*@ 8258 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8259 `MatGetColumnIJ()`. 8260 8261 Collective 8262 8263 Input Parameters: 8264 + mat - the matrix 8265 . ncolors - maximum color value 8266 . n - number of entries in colorarray 8267 - colorarray - array indicating color for each column 8268 8269 Output Parameter: 8270 . iscoloring - coloring generated using colorarray information 8271 8272 Level: developer 8273 8274 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8275 @*/ 8276 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8277 { 8278 PetscFunctionBegin; 8279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8280 PetscValidType(mat, 1); 8281 PetscAssertPointer(colorarray, 4); 8282 PetscAssertPointer(iscoloring, 5); 8283 MatCheckPreallocated(mat, 1); 8284 8285 if (!mat->ops->coloringpatch) { 8286 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8287 } else { 8288 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8289 } 8290 PetscFunctionReturn(PETSC_SUCCESS); 8291 } 8292 8293 /*@ 8294 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8295 8296 Logically Collective 8297 8298 Input Parameter: 8299 . mat - the factored matrix to be reset 8300 8301 Level: developer 8302 8303 Notes: 8304 This routine should be used only with factored matrices formed by in-place 8305 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8306 format). This option can save memory, for example, when solving nonlinear 8307 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8308 ILU(0) preconditioner. 8309 8310 One can specify in-place ILU(0) factorization by calling 8311 .vb 8312 PCType(pc,PCILU); 8313 PCFactorSeUseInPlace(pc); 8314 .ve 8315 or by using the options -pc_type ilu -pc_factor_in_place 8316 8317 In-place factorization ILU(0) can also be used as a local 8318 solver for the blocks within the block Jacobi or additive Schwarz 8319 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8320 for details on setting local solver options. 8321 8322 Most users should employ the `KSP` interface for linear solvers 8323 instead of working directly with matrix algebra routines such as this. 8324 See, e.g., `KSPCreate()`. 8325 8326 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8327 @*/ 8328 PetscErrorCode MatSetUnfactored(Mat mat) 8329 { 8330 PetscFunctionBegin; 8331 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8332 PetscValidType(mat, 1); 8333 MatCheckPreallocated(mat, 1); 8334 mat->factortype = MAT_FACTOR_NONE; 8335 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8336 PetscUseTypeMethod(mat, setunfactored); 8337 PetscFunctionReturn(PETSC_SUCCESS); 8338 } 8339 8340 /*@ 8341 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8342 as the original matrix. 8343 8344 Collective 8345 8346 Input Parameters: 8347 + mat - the original matrix 8348 . isrow - parallel `IS` containing the rows this processor should obtain 8349 . 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. 8350 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8351 8352 Output Parameter: 8353 . newmat - the new submatrix, of the same type as the original matrix 8354 8355 Level: advanced 8356 8357 Notes: 8358 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8359 8360 Some matrix types place restrictions on the row and column indices, such 8361 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; 8362 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8363 8364 The index sets may not have duplicate entries. 8365 8366 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8367 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8368 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8369 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8370 you are finished using it. 8371 8372 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8373 the input matrix. 8374 8375 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8376 8377 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8378 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8379 8380 Example usage: 8381 Consider the following 8x8 matrix with 34 non-zero values, that is 8382 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8383 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8384 as follows 8385 .vb 8386 1 2 0 | 0 3 0 | 0 4 8387 Proc0 0 5 6 | 7 0 0 | 8 0 8388 9 0 10 | 11 0 0 | 12 0 8389 ------------------------------------- 8390 13 0 14 | 15 16 17 | 0 0 8391 Proc1 0 18 0 | 19 20 21 | 0 0 8392 0 0 0 | 22 23 0 | 24 0 8393 ------------------------------------- 8394 Proc2 25 26 27 | 0 0 28 | 29 0 8395 30 0 0 | 31 32 33 | 0 34 8396 .ve 8397 8398 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8399 8400 .vb 8401 2 0 | 0 3 0 | 0 8402 Proc0 5 6 | 7 0 0 | 8 8403 ------------------------------- 8404 Proc1 18 0 | 19 20 21 | 0 8405 ------------------------------- 8406 Proc2 26 27 | 0 0 28 | 29 8407 0 0 | 31 32 33 | 0 8408 .ve 8409 8410 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8411 @*/ 8412 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8413 { 8414 PetscMPIInt size; 8415 Mat *local; 8416 IS iscoltmp; 8417 PetscBool flg; 8418 8419 PetscFunctionBegin; 8420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8421 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8422 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8423 PetscAssertPointer(newmat, 5); 8424 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8425 PetscValidType(mat, 1); 8426 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8427 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8428 8429 MatCheckPreallocated(mat, 1); 8430 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8431 8432 if (!iscol || isrow == iscol) { 8433 PetscBool stride; 8434 PetscMPIInt grabentirematrix = 0, grab; 8435 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8436 if (stride) { 8437 PetscInt first, step, n, rstart, rend; 8438 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8439 if (step == 1) { 8440 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8441 if (rstart == first) { 8442 PetscCall(ISGetLocalSize(isrow, &n)); 8443 if (n == rend - rstart) grabentirematrix = 1; 8444 } 8445 } 8446 } 8447 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8448 if (grab) { 8449 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8450 if (cll == MAT_INITIAL_MATRIX) { 8451 *newmat = mat; 8452 PetscCall(PetscObjectReference((PetscObject)mat)); 8453 } 8454 PetscFunctionReturn(PETSC_SUCCESS); 8455 } 8456 } 8457 8458 if (!iscol) { 8459 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8460 } else { 8461 iscoltmp = iscol; 8462 } 8463 8464 /* if original matrix is on just one processor then use submatrix generated */ 8465 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8466 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8467 goto setproperties; 8468 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8469 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8470 *newmat = *local; 8471 PetscCall(PetscFree(local)); 8472 goto setproperties; 8473 } else if (!mat->ops->createsubmatrix) { 8474 /* Create a new matrix type that implements the operation using the full matrix */ 8475 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8476 switch (cll) { 8477 case MAT_INITIAL_MATRIX: 8478 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8479 break; 8480 case MAT_REUSE_MATRIX: 8481 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8482 break; 8483 default: 8484 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8485 } 8486 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8487 goto setproperties; 8488 } 8489 8490 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8491 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8492 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8493 8494 setproperties: 8495 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8496 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8497 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8498 } 8499 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8500 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8501 PetscFunctionReturn(PETSC_SUCCESS); 8502 } 8503 8504 /*@ 8505 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8506 8507 Not Collective 8508 8509 Input Parameters: 8510 + A - the matrix we wish to propagate options from 8511 - B - the matrix we wish to propagate options to 8512 8513 Level: beginner 8514 8515 Note: 8516 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8517 8518 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8519 @*/ 8520 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8521 { 8522 PetscFunctionBegin; 8523 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8524 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8525 B->symmetry_eternal = A->symmetry_eternal; 8526 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8527 B->symmetric = A->symmetric; 8528 B->structurally_symmetric = A->structurally_symmetric; 8529 B->spd = A->spd; 8530 B->hermitian = A->hermitian; 8531 PetscFunctionReturn(PETSC_SUCCESS); 8532 } 8533 8534 /*@ 8535 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8536 used during the assembly process to store values that belong to 8537 other processors. 8538 8539 Not Collective 8540 8541 Input Parameters: 8542 + mat - the matrix 8543 . size - the initial size of the stash. 8544 - bsize - the initial size of the block-stash(if used). 8545 8546 Options Database Keys: 8547 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8548 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8549 8550 Level: intermediate 8551 8552 Notes: 8553 The block-stash is used for values set with `MatSetValuesBlocked()` while 8554 the stash is used for values set with `MatSetValues()` 8555 8556 Run with the option -info and look for output of the form 8557 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8558 to determine the appropriate value, MM, to use for size and 8559 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8560 to determine the value, BMM to use for bsize 8561 8562 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8563 @*/ 8564 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8565 { 8566 PetscFunctionBegin; 8567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8568 PetscValidType(mat, 1); 8569 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8570 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8571 PetscFunctionReturn(PETSC_SUCCESS); 8572 } 8573 8574 /*@ 8575 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8576 the matrix 8577 8578 Neighbor-wise Collective 8579 8580 Input Parameters: 8581 + A - the matrix 8582 . x - the vector to be multiplied by the interpolation operator 8583 - y - the vector to be added to the result 8584 8585 Output Parameter: 8586 . w - the resulting vector 8587 8588 Level: intermediate 8589 8590 Notes: 8591 `w` may be the same vector as `y`. 8592 8593 This allows one to use either the restriction or interpolation (its transpose) 8594 matrix to do the interpolation 8595 8596 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8597 @*/ 8598 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8599 { 8600 PetscInt M, N, Ny; 8601 8602 PetscFunctionBegin; 8603 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8604 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8605 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8606 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8607 PetscCall(MatGetSize(A, &M, &N)); 8608 PetscCall(VecGetSize(y, &Ny)); 8609 if (M == Ny) { 8610 PetscCall(MatMultAdd(A, x, y, w)); 8611 } else { 8612 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8613 } 8614 PetscFunctionReturn(PETSC_SUCCESS); 8615 } 8616 8617 /*@ 8618 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8619 the matrix 8620 8621 Neighbor-wise Collective 8622 8623 Input Parameters: 8624 + A - the matrix 8625 - x - the vector to be interpolated 8626 8627 Output Parameter: 8628 . y - the resulting vector 8629 8630 Level: intermediate 8631 8632 Note: 8633 This allows one to use either the restriction or interpolation (its transpose) 8634 matrix to do the interpolation 8635 8636 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8637 @*/ 8638 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8639 { 8640 PetscInt M, N, Ny; 8641 8642 PetscFunctionBegin; 8643 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8644 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8645 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8646 PetscCall(MatGetSize(A, &M, &N)); 8647 PetscCall(VecGetSize(y, &Ny)); 8648 if (M == Ny) { 8649 PetscCall(MatMult(A, x, y)); 8650 } else { 8651 PetscCall(MatMultTranspose(A, x, y)); 8652 } 8653 PetscFunctionReturn(PETSC_SUCCESS); 8654 } 8655 8656 /*@ 8657 MatRestrict - $y = A*x$ or $A^T*x$ 8658 8659 Neighbor-wise Collective 8660 8661 Input Parameters: 8662 + A - the matrix 8663 - x - the vector to be restricted 8664 8665 Output Parameter: 8666 . y - the resulting vector 8667 8668 Level: intermediate 8669 8670 Note: 8671 This allows one to use either the restriction or interpolation (its transpose) 8672 matrix to do the restriction 8673 8674 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8675 @*/ 8676 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8677 { 8678 PetscInt M, N, Nx; 8679 8680 PetscFunctionBegin; 8681 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8682 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8683 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8684 PetscCall(MatGetSize(A, &M, &N)); 8685 PetscCall(VecGetSize(x, &Nx)); 8686 if (M == Nx) { 8687 PetscCall(MatMultTranspose(A, x, y)); 8688 } else { 8689 PetscCall(MatMult(A, x, y)); 8690 } 8691 PetscFunctionReturn(PETSC_SUCCESS); 8692 } 8693 8694 /*@ 8695 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8696 8697 Neighbor-wise Collective 8698 8699 Input Parameters: 8700 + A - the matrix 8701 . x - the input dense matrix to be multiplied 8702 - w - the input dense matrix to be added to the result 8703 8704 Output Parameter: 8705 . y - the output dense matrix 8706 8707 Level: intermediate 8708 8709 Note: 8710 This allows one to use either the restriction or interpolation (its transpose) 8711 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8712 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8713 8714 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8715 @*/ 8716 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8717 { 8718 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8719 PetscBool trans = PETSC_TRUE; 8720 MatReuse reuse = MAT_INITIAL_MATRIX; 8721 8722 PetscFunctionBegin; 8723 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8724 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8725 PetscValidType(x, 2); 8726 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8727 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8728 PetscCall(MatGetSize(A, &M, &N)); 8729 PetscCall(MatGetSize(x, &Mx, &Nx)); 8730 if (N == Mx) trans = PETSC_FALSE; 8731 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); 8732 Mo = trans ? N : M; 8733 if (*y) { 8734 PetscCall(MatGetSize(*y, &My, &Ny)); 8735 if (Mo == My && Nx == Ny) { 8736 reuse = MAT_REUSE_MATRIX; 8737 } else { 8738 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); 8739 PetscCall(MatDestroy(y)); 8740 } 8741 } 8742 8743 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8744 PetscBool flg; 8745 8746 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8747 if (w) { 8748 PetscInt My, Ny, Mw, Nw; 8749 8750 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8751 PetscCall(MatGetSize(*y, &My, &Ny)); 8752 PetscCall(MatGetSize(w, &Mw, &Nw)); 8753 if (!flg || My != Mw || Ny != Nw) w = NULL; 8754 } 8755 if (!w) { 8756 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8757 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8758 PetscCall(PetscObjectDereference((PetscObject)w)); 8759 } else { 8760 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8761 } 8762 } 8763 if (!trans) { 8764 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8765 } else { 8766 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8767 } 8768 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8769 PetscFunctionReturn(PETSC_SUCCESS); 8770 } 8771 8772 /*@ 8773 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8774 8775 Neighbor-wise Collective 8776 8777 Input Parameters: 8778 + A - the matrix 8779 - x - the input dense matrix 8780 8781 Output Parameter: 8782 . y - the output dense matrix 8783 8784 Level: intermediate 8785 8786 Note: 8787 This allows one to use either the restriction or interpolation (its transpose) 8788 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8789 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8790 8791 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8792 @*/ 8793 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8794 { 8795 PetscFunctionBegin; 8796 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8797 PetscFunctionReturn(PETSC_SUCCESS); 8798 } 8799 8800 /*@ 8801 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8802 8803 Neighbor-wise Collective 8804 8805 Input Parameters: 8806 + A - the matrix 8807 - x - the input dense matrix 8808 8809 Output Parameter: 8810 . y - the output dense matrix 8811 8812 Level: intermediate 8813 8814 Note: 8815 This allows one to use either the restriction or interpolation (its transpose) 8816 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8817 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8818 8819 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8820 @*/ 8821 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8822 { 8823 PetscFunctionBegin; 8824 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8825 PetscFunctionReturn(PETSC_SUCCESS); 8826 } 8827 8828 /*@ 8829 MatGetNullSpace - retrieves the null space of a matrix. 8830 8831 Logically Collective 8832 8833 Input Parameters: 8834 + mat - the matrix 8835 - nullsp - the null space object 8836 8837 Level: developer 8838 8839 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8840 @*/ 8841 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8842 { 8843 PetscFunctionBegin; 8844 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8845 PetscAssertPointer(nullsp, 2); 8846 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8847 PetscFunctionReturn(PETSC_SUCCESS); 8848 } 8849 8850 /*@C 8851 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8852 8853 Logically Collective 8854 8855 Input Parameters: 8856 + n - the number of matrices 8857 - mat - the array of matrices 8858 8859 Output Parameters: 8860 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8861 8862 Level: developer 8863 8864 Note: 8865 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8866 8867 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8868 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8869 @*/ 8870 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8871 { 8872 PetscFunctionBegin; 8873 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8874 PetscAssertPointer(mat, 2); 8875 PetscAssertPointer(nullsp, 3); 8876 8877 PetscCall(PetscCalloc1(3 * n, nullsp)); 8878 for (PetscInt i = 0; i < n; i++) { 8879 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8880 (*nullsp)[i] = mat[i]->nullsp; 8881 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8882 (*nullsp)[n + i] = mat[i]->nearnullsp; 8883 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8884 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8885 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8886 } 8887 PetscFunctionReturn(PETSC_SUCCESS); 8888 } 8889 8890 /*@C 8891 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8892 8893 Logically Collective 8894 8895 Input Parameters: 8896 + n - the number of matrices 8897 . mat - the array of matrices 8898 - nullsp - an array of null spaces 8899 8900 Level: developer 8901 8902 Note: 8903 Call `MatGetNullSpaces()` to create `nullsp` 8904 8905 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8906 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8907 @*/ 8908 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8909 { 8910 PetscFunctionBegin; 8911 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8912 PetscAssertPointer(mat, 2); 8913 PetscAssertPointer(nullsp, 3); 8914 PetscAssertPointer(*nullsp, 3); 8915 8916 for (PetscInt i = 0; i < n; i++) { 8917 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8918 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8919 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8920 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8921 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8922 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8923 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8924 } 8925 PetscCall(PetscFree(*nullsp)); 8926 PetscFunctionReturn(PETSC_SUCCESS); 8927 } 8928 8929 /*@ 8930 MatSetNullSpace - attaches a null space to a matrix. 8931 8932 Logically Collective 8933 8934 Input Parameters: 8935 + mat - the matrix 8936 - nullsp - the null space object 8937 8938 Level: advanced 8939 8940 Notes: 8941 This null space is used by the `KSP` linear solvers to solve singular systems. 8942 8943 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` 8944 8945 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 8946 to zero but the linear system will still be solved in a least squares sense. 8947 8948 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8949 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)$. 8950 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 8951 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 8952 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$). 8953 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8954 8955 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8956 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8957 routine also automatically calls `MatSetTransposeNullSpace()`. 8958 8959 The user should call `MatNullSpaceDestroy()`. 8960 8961 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8962 `KSPSetPCSide()` 8963 @*/ 8964 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8965 { 8966 PetscFunctionBegin; 8967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8968 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8969 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8970 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8971 mat->nullsp = nullsp; 8972 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8973 PetscFunctionReturn(PETSC_SUCCESS); 8974 } 8975 8976 /*@ 8977 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8978 8979 Logically Collective 8980 8981 Input Parameters: 8982 + mat - the matrix 8983 - nullsp - the null space object 8984 8985 Level: developer 8986 8987 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8988 @*/ 8989 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8990 { 8991 PetscFunctionBegin; 8992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8993 PetscValidType(mat, 1); 8994 PetscAssertPointer(nullsp, 2); 8995 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8996 PetscFunctionReturn(PETSC_SUCCESS); 8997 } 8998 8999 /*@ 9000 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9001 9002 Logically Collective 9003 9004 Input Parameters: 9005 + mat - the matrix 9006 - nullsp - the null space object 9007 9008 Level: advanced 9009 9010 Notes: 9011 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9012 9013 See `MatSetNullSpace()` 9014 9015 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9016 @*/ 9017 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9018 { 9019 PetscFunctionBegin; 9020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9021 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9022 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9023 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9024 mat->transnullsp = nullsp; 9025 PetscFunctionReturn(PETSC_SUCCESS); 9026 } 9027 9028 /*@ 9029 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9030 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9031 9032 Logically Collective 9033 9034 Input Parameters: 9035 + mat - the matrix 9036 - nullsp - the null space object 9037 9038 Level: advanced 9039 9040 Notes: 9041 Overwrites any previous near null space that may have been attached 9042 9043 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9044 9045 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9046 @*/ 9047 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9048 { 9049 PetscFunctionBegin; 9050 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9051 PetscValidType(mat, 1); 9052 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9053 MatCheckPreallocated(mat, 1); 9054 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9055 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9056 mat->nearnullsp = nullsp; 9057 PetscFunctionReturn(PETSC_SUCCESS); 9058 } 9059 9060 /*@ 9061 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9062 9063 Not Collective 9064 9065 Input Parameter: 9066 . mat - the matrix 9067 9068 Output Parameter: 9069 . nullsp - the null space object, `NULL` if not set 9070 9071 Level: advanced 9072 9073 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9074 @*/ 9075 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9076 { 9077 PetscFunctionBegin; 9078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9079 PetscValidType(mat, 1); 9080 PetscAssertPointer(nullsp, 2); 9081 MatCheckPreallocated(mat, 1); 9082 *nullsp = mat->nearnullsp; 9083 PetscFunctionReturn(PETSC_SUCCESS); 9084 } 9085 9086 /*@ 9087 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9088 9089 Collective 9090 9091 Input Parameters: 9092 + mat - the matrix 9093 . row - row/column permutation 9094 - info - information on desired factorization process 9095 9096 Level: developer 9097 9098 Notes: 9099 Probably really in-place only when level of fill is zero, otherwise allocates 9100 new space to store factored matrix and deletes previous memory. 9101 9102 Most users should employ the `KSP` interface for linear solvers 9103 instead of working directly with matrix algebra routines such as this. 9104 See, e.g., `KSPCreate()`. 9105 9106 Developer Note: 9107 The Fortran interface is not autogenerated as the 9108 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9109 9110 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9111 @*/ 9112 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9113 { 9114 PetscFunctionBegin; 9115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9116 PetscValidType(mat, 1); 9117 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9118 PetscAssertPointer(info, 3); 9119 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9120 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9121 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9122 MatCheckPreallocated(mat, 1); 9123 PetscUseTypeMethod(mat, iccfactor, row, info); 9124 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9125 PetscFunctionReturn(PETSC_SUCCESS); 9126 } 9127 9128 /*@ 9129 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9130 ghosted ones. 9131 9132 Not Collective 9133 9134 Input Parameters: 9135 + mat - the matrix 9136 - diag - the diagonal values, including ghost ones 9137 9138 Level: developer 9139 9140 Notes: 9141 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9142 9143 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9144 9145 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9146 @*/ 9147 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9148 { 9149 PetscMPIInt size; 9150 9151 PetscFunctionBegin; 9152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9153 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9154 PetscValidType(mat, 1); 9155 9156 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9157 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9158 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9159 if (size == 1) { 9160 PetscInt n, m; 9161 PetscCall(VecGetSize(diag, &n)); 9162 PetscCall(MatGetSize(mat, NULL, &m)); 9163 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9164 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9165 } else { 9166 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9167 } 9168 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9169 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9170 PetscFunctionReturn(PETSC_SUCCESS); 9171 } 9172 9173 /*@ 9174 MatGetInertia - Gets the inertia from a factored matrix 9175 9176 Collective 9177 9178 Input Parameter: 9179 . mat - the matrix 9180 9181 Output Parameters: 9182 + nneg - number of negative eigenvalues 9183 . nzero - number of zero eigenvalues 9184 - npos - number of positive eigenvalues 9185 9186 Level: advanced 9187 9188 Note: 9189 Matrix must have been factored by `MatCholeskyFactor()` 9190 9191 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9192 @*/ 9193 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9194 { 9195 PetscFunctionBegin; 9196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9197 PetscValidType(mat, 1); 9198 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9199 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9200 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9201 PetscFunctionReturn(PETSC_SUCCESS); 9202 } 9203 9204 /*@C 9205 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9206 9207 Neighbor-wise Collective 9208 9209 Input Parameters: 9210 + mat - the factored matrix obtained with `MatGetFactor()` 9211 - b - the right-hand-side vectors 9212 9213 Output Parameter: 9214 . x - the result vectors 9215 9216 Level: developer 9217 9218 Note: 9219 The vectors `b` and `x` cannot be the same. I.e., one cannot 9220 call `MatSolves`(A,x,x). 9221 9222 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9223 @*/ 9224 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9225 { 9226 PetscFunctionBegin; 9227 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9228 PetscValidType(mat, 1); 9229 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9230 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9231 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9232 9233 MatCheckPreallocated(mat, 1); 9234 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9235 PetscUseTypeMethod(mat, solves, b, x); 9236 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9237 PetscFunctionReturn(PETSC_SUCCESS); 9238 } 9239 9240 /*@ 9241 MatIsSymmetric - Test whether a matrix is symmetric 9242 9243 Collective 9244 9245 Input Parameters: 9246 + A - the matrix to test 9247 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9248 9249 Output Parameter: 9250 . flg - the result 9251 9252 Level: intermediate 9253 9254 Notes: 9255 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9256 9257 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9258 9259 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9260 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9261 9262 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9263 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9264 @*/ 9265 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9266 { 9267 PetscFunctionBegin; 9268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9269 PetscAssertPointer(flg, 3); 9270 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9271 else { 9272 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9273 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9274 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9275 } 9276 PetscFunctionReturn(PETSC_SUCCESS); 9277 } 9278 9279 /*@ 9280 MatIsHermitian - Test whether a matrix is Hermitian 9281 9282 Collective 9283 9284 Input Parameters: 9285 + A - the matrix to test 9286 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9287 9288 Output Parameter: 9289 . flg - the result 9290 9291 Level: intermediate 9292 9293 Notes: 9294 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9295 9296 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9297 9298 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9299 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9300 9301 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9302 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9303 @*/ 9304 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9305 { 9306 PetscFunctionBegin; 9307 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9308 PetscAssertPointer(flg, 3); 9309 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9310 else { 9311 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9312 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9313 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9314 } 9315 PetscFunctionReturn(PETSC_SUCCESS); 9316 } 9317 9318 /*@ 9319 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9320 9321 Not Collective 9322 9323 Input Parameter: 9324 . A - the matrix to check 9325 9326 Output Parameters: 9327 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9328 - flg - the result (only valid if set is `PETSC_TRUE`) 9329 9330 Level: advanced 9331 9332 Notes: 9333 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9334 if you want it explicitly checked 9335 9336 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9337 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9338 9339 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9340 @*/ 9341 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9342 { 9343 PetscFunctionBegin; 9344 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9345 PetscAssertPointer(set, 2); 9346 PetscAssertPointer(flg, 3); 9347 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9348 *set = PETSC_TRUE; 9349 *flg = PetscBool3ToBool(A->symmetric); 9350 } else { 9351 *set = PETSC_FALSE; 9352 } 9353 PetscFunctionReturn(PETSC_SUCCESS); 9354 } 9355 9356 /*@ 9357 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9358 9359 Not Collective 9360 9361 Input Parameter: 9362 . A - the matrix to check 9363 9364 Output Parameters: 9365 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9366 - flg - the result (only valid if set is `PETSC_TRUE`) 9367 9368 Level: advanced 9369 9370 Notes: 9371 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9372 9373 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9374 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9375 9376 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9377 @*/ 9378 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9379 { 9380 PetscFunctionBegin; 9381 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9382 PetscAssertPointer(set, 2); 9383 PetscAssertPointer(flg, 3); 9384 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9385 *set = PETSC_TRUE; 9386 *flg = PetscBool3ToBool(A->spd); 9387 } else { 9388 *set = PETSC_FALSE; 9389 } 9390 PetscFunctionReturn(PETSC_SUCCESS); 9391 } 9392 9393 /*@ 9394 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9395 9396 Not Collective 9397 9398 Input Parameter: 9399 . A - the matrix to check 9400 9401 Output Parameters: 9402 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9403 - flg - the result (only valid if set is `PETSC_TRUE`) 9404 9405 Level: advanced 9406 9407 Notes: 9408 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9409 if you want it explicitly checked 9410 9411 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9412 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9413 9414 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9415 @*/ 9416 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9417 { 9418 PetscFunctionBegin; 9419 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9420 PetscAssertPointer(set, 2); 9421 PetscAssertPointer(flg, 3); 9422 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9423 *set = PETSC_TRUE; 9424 *flg = PetscBool3ToBool(A->hermitian); 9425 } else { 9426 *set = PETSC_FALSE; 9427 } 9428 PetscFunctionReturn(PETSC_SUCCESS); 9429 } 9430 9431 /*@ 9432 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9433 9434 Collective 9435 9436 Input Parameter: 9437 . A - the matrix to test 9438 9439 Output Parameter: 9440 . flg - the result 9441 9442 Level: intermediate 9443 9444 Notes: 9445 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9446 9447 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 9448 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9449 9450 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9451 @*/ 9452 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9453 { 9454 PetscFunctionBegin; 9455 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9456 PetscAssertPointer(flg, 2); 9457 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9458 *flg = PetscBool3ToBool(A->structurally_symmetric); 9459 } else { 9460 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9461 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9462 } 9463 PetscFunctionReturn(PETSC_SUCCESS); 9464 } 9465 9466 /*@ 9467 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9468 9469 Not Collective 9470 9471 Input Parameter: 9472 . A - the matrix to check 9473 9474 Output Parameters: 9475 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9476 - flg - the result (only valid if set is PETSC_TRUE) 9477 9478 Level: advanced 9479 9480 Notes: 9481 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 9482 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9483 9484 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9485 9486 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9487 @*/ 9488 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9489 { 9490 PetscFunctionBegin; 9491 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9492 PetscAssertPointer(set, 2); 9493 PetscAssertPointer(flg, 3); 9494 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9495 *set = PETSC_TRUE; 9496 *flg = PetscBool3ToBool(A->structurally_symmetric); 9497 } else { 9498 *set = PETSC_FALSE; 9499 } 9500 PetscFunctionReturn(PETSC_SUCCESS); 9501 } 9502 9503 /*@ 9504 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9505 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9506 9507 Not Collective 9508 9509 Input Parameter: 9510 . mat - the matrix 9511 9512 Output Parameters: 9513 + nstash - the size of the stash 9514 . reallocs - the number of additional mallocs incurred. 9515 . bnstash - the size of the block stash 9516 - breallocs - the number of additional mallocs incurred.in the block stash 9517 9518 Level: advanced 9519 9520 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9521 @*/ 9522 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9523 { 9524 PetscFunctionBegin; 9525 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9526 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9527 PetscFunctionReturn(PETSC_SUCCESS); 9528 } 9529 9530 /*@ 9531 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9532 parallel layout, `PetscLayout` for rows and columns 9533 9534 Collective 9535 9536 Input Parameter: 9537 . mat - the matrix 9538 9539 Output Parameters: 9540 + right - (optional) vector that the matrix can be multiplied against 9541 - left - (optional) vector that the matrix vector product can be stored in 9542 9543 Level: advanced 9544 9545 Notes: 9546 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()`. 9547 9548 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9549 9550 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9551 @*/ 9552 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9553 { 9554 PetscFunctionBegin; 9555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9556 PetscValidType(mat, 1); 9557 if (mat->ops->getvecs) { 9558 PetscUseTypeMethod(mat, getvecs, right, left); 9559 } else { 9560 if (right) { 9561 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9562 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9563 PetscCall(VecSetType(*right, mat->defaultvectype)); 9564 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9565 if (mat->boundtocpu && mat->bindingpropagates) { 9566 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9567 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9568 } 9569 #endif 9570 } 9571 if (left) { 9572 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9573 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9574 PetscCall(VecSetType(*left, mat->defaultvectype)); 9575 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9576 if (mat->boundtocpu && mat->bindingpropagates) { 9577 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9578 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9579 } 9580 #endif 9581 } 9582 } 9583 PetscFunctionReturn(PETSC_SUCCESS); 9584 } 9585 9586 /*@ 9587 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9588 with default values. 9589 9590 Not Collective 9591 9592 Input Parameter: 9593 . info - the `MatFactorInfo` data structure 9594 9595 Level: developer 9596 9597 Notes: 9598 The solvers are generally used through the `KSP` and `PC` objects, for example 9599 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9600 9601 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9602 9603 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9604 @*/ 9605 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9606 { 9607 PetscFunctionBegin; 9608 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9609 PetscFunctionReturn(PETSC_SUCCESS); 9610 } 9611 9612 /*@ 9613 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9614 9615 Collective 9616 9617 Input Parameters: 9618 + mat - the factored matrix 9619 - is - the index set defining the Schur indices (0-based) 9620 9621 Level: advanced 9622 9623 Notes: 9624 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9625 9626 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9627 9628 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9629 9630 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9631 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9632 @*/ 9633 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9634 { 9635 PetscErrorCode (*f)(Mat, IS); 9636 9637 PetscFunctionBegin; 9638 PetscValidType(mat, 1); 9639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9640 PetscValidType(is, 2); 9641 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9642 PetscCheckSameComm(mat, 1, is, 2); 9643 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9644 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9645 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9646 PetscCall(MatDestroy(&mat->schur)); 9647 PetscCall((*f)(mat, is)); 9648 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9649 PetscFunctionReturn(PETSC_SUCCESS); 9650 } 9651 9652 /*@ 9653 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9654 9655 Logically Collective 9656 9657 Input Parameters: 9658 + F - the factored matrix obtained by calling `MatGetFactor()` 9659 . S - location where to return the Schur complement, can be `NULL` 9660 - status - the status of the Schur complement matrix, can be `NULL` 9661 9662 Level: advanced 9663 9664 Notes: 9665 You must call `MatFactorSetSchurIS()` before calling this routine. 9666 9667 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9668 9669 The routine provides a copy of the Schur matrix stored within the solver data structures. 9670 The caller must destroy the object when it is no longer needed. 9671 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9672 9673 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) 9674 9675 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9676 9677 Developer Note: 9678 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9679 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9680 9681 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9682 @*/ 9683 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9684 { 9685 PetscFunctionBegin; 9686 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9687 if (S) PetscAssertPointer(S, 2); 9688 if (status) PetscAssertPointer(status, 3); 9689 if (S) { 9690 PetscErrorCode (*f)(Mat, Mat *); 9691 9692 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9693 if (f) { 9694 PetscCall((*f)(F, S)); 9695 } else { 9696 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9697 } 9698 } 9699 if (status) *status = F->schur_status; 9700 PetscFunctionReturn(PETSC_SUCCESS); 9701 } 9702 9703 /*@ 9704 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9705 9706 Logically Collective 9707 9708 Input Parameters: 9709 + F - the factored matrix obtained by calling `MatGetFactor()` 9710 . S - location where to return the Schur complement, can be `NULL` 9711 - status - the status of the Schur complement matrix, can be `NULL` 9712 9713 Level: advanced 9714 9715 Notes: 9716 You must call `MatFactorSetSchurIS()` before calling this routine. 9717 9718 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9719 9720 The routine returns a the Schur Complement stored within the data structures of the solver. 9721 9722 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9723 9724 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9725 9726 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9727 9728 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9729 9730 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9731 @*/ 9732 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9733 { 9734 PetscFunctionBegin; 9735 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9736 if (S) { 9737 PetscAssertPointer(S, 2); 9738 *S = F->schur; 9739 } 9740 if (status) { 9741 PetscAssertPointer(status, 3); 9742 *status = F->schur_status; 9743 } 9744 PetscFunctionReturn(PETSC_SUCCESS); 9745 } 9746 9747 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9748 { 9749 Mat S = F->schur; 9750 9751 PetscFunctionBegin; 9752 switch (F->schur_status) { 9753 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9754 case MAT_FACTOR_SCHUR_INVERTED: 9755 if (S) { 9756 S->ops->solve = NULL; 9757 S->ops->matsolve = NULL; 9758 S->ops->solvetranspose = NULL; 9759 S->ops->matsolvetranspose = NULL; 9760 S->ops->solveadd = NULL; 9761 S->ops->solvetransposeadd = NULL; 9762 S->factortype = MAT_FACTOR_NONE; 9763 PetscCall(PetscFree(S->solvertype)); 9764 } 9765 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9766 break; 9767 default: 9768 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9769 } 9770 PetscFunctionReturn(PETSC_SUCCESS); 9771 } 9772 9773 /*@ 9774 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9775 9776 Logically Collective 9777 9778 Input Parameters: 9779 + F - the factored matrix obtained by calling `MatGetFactor()` 9780 . S - location where the Schur complement is stored 9781 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9782 9783 Level: advanced 9784 9785 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9786 @*/ 9787 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9788 { 9789 PetscFunctionBegin; 9790 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9791 if (S) { 9792 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9793 *S = NULL; 9794 } 9795 F->schur_status = status; 9796 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9797 PetscFunctionReturn(PETSC_SUCCESS); 9798 } 9799 9800 /*@ 9801 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9802 9803 Logically Collective 9804 9805 Input Parameters: 9806 + F - the factored matrix obtained by calling `MatGetFactor()` 9807 . rhs - location where the right-hand side of the Schur complement system is stored 9808 - sol - location where the solution of the Schur complement system has to be returned 9809 9810 Level: advanced 9811 9812 Notes: 9813 The sizes of the vectors should match the size of the Schur complement 9814 9815 Must be called after `MatFactorSetSchurIS()` 9816 9817 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9818 @*/ 9819 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9820 { 9821 PetscFunctionBegin; 9822 PetscValidType(F, 1); 9823 PetscValidType(rhs, 2); 9824 PetscValidType(sol, 3); 9825 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9826 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9827 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9828 PetscCheckSameComm(F, 1, rhs, 2); 9829 PetscCheckSameComm(F, 1, sol, 3); 9830 PetscCall(MatFactorFactorizeSchurComplement(F)); 9831 switch (F->schur_status) { 9832 case MAT_FACTOR_SCHUR_FACTORED: 9833 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9834 break; 9835 case MAT_FACTOR_SCHUR_INVERTED: 9836 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9837 break; 9838 default: 9839 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9840 } 9841 PetscFunctionReturn(PETSC_SUCCESS); 9842 } 9843 9844 /*@ 9845 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9846 9847 Logically Collective 9848 9849 Input Parameters: 9850 + F - the factored matrix obtained by calling `MatGetFactor()` 9851 . rhs - location where the right-hand side of the Schur complement system is stored 9852 - sol - location where the solution of the Schur complement system has to be returned 9853 9854 Level: advanced 9855 9856 Notes: 9857 The sizes of the vectors should match the size of the Schur complement 9858 9859 Must be called after `MatFactorSetSchurIS()` 9860 9861 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9862 @*/ 9863 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9864 { 9865 PetscFunctionBegin; 9866 PetscValidType(F, 1); 9867 PetscValidType(rhs, 2); 9868 PetscValidType(sol, 3); 9869 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9870 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9871 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9872 PetscCheckSameComm(F, 1, rhs, 2); 9873 PetscCheckSameComm(F, 1, sol, 3); 9874 PetscCall(MatFactorFactorizeSchurComplement(F)); 9875 switch (F->schur_status) { 9876 case MAT_FACTOR_SCHUR_FACTORED: 9877 PetscCall(MatSolve(F->schur, rhs, sol)); 9878 break; 9879 case MAT_FACTOR_SCHUR_INVERTED: 9880 PetscCall(MatMult(F->schur, rhs, sol)); 9881 break; 9882 default: 9883 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9884 } 9885 PetscFunctionReturn(PETSC_SUCCESS); 9886 } 9887 9888 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9889 #if PetscDefined(HAVE_CUDA) 9890 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9891 #endif 9892 9893 /* Schur status updated in the interface */ 9894 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9895 { 9896 Mat S = F->schur; 9897 9898 PetscFunctionBegin; 9899 if (S) { 9900 PetscMPIInt size; 9901 PetscBool isdense, isdensecuda; 9902 9903 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9904 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9905 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9906 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9907 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9908 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9909 if (isdense) { 9910 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9911 } else if (isdensecuda) { 9912 #if defined(PETSC_HAVE_CUDA) 9913 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9914 #endif 9915 } 9916 // HIP?????????????? 9917 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9918 } 9919 PetscFunctionReturn(PETSC_SUCCESS); 9920 } 9921 9922 /*@ 9923 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9924 9925 Logically Collective 9926 9927 Input Parameter: 9928 . F - the factored matrix obtained by calling `MatGetFactor()` 9929 9930 Level: advanced 9931 9932 Notes: 9933 Must be called after `MatFactorSetSchurIS()`. 9934 9935 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9936 9937 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9938 @*/ 9939 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9940 { 9941 PetscFunctionBegin; 9942 PetscValidType(F, 1); 9943 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9944 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9945 PetscCall(MatFactorFactorizeSchurComplement(F)); 9946 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9947 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9948 PetscFunctionReturn(PETSC_SUCCESS); 9949 } 9950 9951 /*@ 9952 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9953 9954 Logically Collective 9955 9956 Input Parameter: 9957 . F - the factored matrix obtained by calling `MatGetFactor()` 9958 9959 Level: advanced 9960 9961 Note: 9962 Must be called after `MatFactorSetSchurIS()` 9963 9964 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9965 @*/ 9966 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9967 { 9968 MatFactorInfo info; 9969 9970 PetscFunctionBegin; 9971 PetscValidType(F, 1); 9972 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9973 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9974 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9975 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9976 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9977 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9978 } else { 9979 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9980 } 9981 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9982 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9983 PetscFunctionReturn(PETSC_SUCCESS); 9984 } 9985 9986 /*@ 9987 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9988 9989 Neighbor-wise Collective 9990 9991 Input Parameters: 9992 + A - the matrix 9993 . P - the projection matrix 9994 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9995 - 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 9996 if the result is a dense matrix this is irrelevant 9997 9998 Output Parameter: 9999 . C - the product matrix 10000 10001 Level: intermediate 10002 10003 Notes: 10004 C will be created and must be destroyed by the user with `MatDestroy()`. 10005 10006 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10007 10008 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10009 10010 Developer Note: 10011 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10012 10013 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10014 @*/ 10015 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10016 { 10017 PetscFunctionBegin; 10018 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10019 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10020 10021 if (scall == MAT_INITIAL_MATRIX) { 10022 PetscCall(MatProductCreate(A, P, NULL, C)); 10023 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10024 PetscCall(MatProductSetAlgorithm(*C, "default")); 10025 PetscCall(MatProductSetFill(*C, fill)); 10026 10027 (*C)->product->api_user = PETSC_TRUE; 10028 PetscCall(MatProductSetFromOptions(*C)); 10029 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); 10030 PetscCall(MatProductSymbolic(*C)); 10031 } else { /* scall == MAT_REUSE_MATRIX */ 10032 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10033 } 10034 10035 PetscCall(MatProductNumeric(*C)); 10036 (*C)->symmetric = A->symmetric; 10037 (*C)->spd = A->spd; 10038 PetscFunctionReturn(PETSC_SUCCESS); 10039 } 10040 10041 /*@ 10042 MatRARt - Creates the matrix product $C = R * A * R^T$ 10043 10044 Neighbor-wise Collective 10045 10046 Input Parameters: 10047 + A - the matrix 10048 . R - the projection matrix 10049 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10050 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10051 if the result is a dense matrix this is irrelevant 10052 10053 Output Parameter: 10054 . C - the product matrix 10055 10056 Level: intermediate 10057 10058 Notes: 10059 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10060 10061 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10062 10063 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10064 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10065 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10066 We recommend using `MatPtAP()` when possible. 10067 10068 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10069 10070 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10071 @*/ 10072 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10073 { 10074 PetscFunctionBegin; 10075 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10076 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10077 10078 if (scall == MAT_INITIAL_MATRIX) { 10079 PetscCall(MatProductCreate(A, R, NULL, C)); 10080 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10081 PetscCall(MatProductSetAlgorithm(*C, "default")); 10082 PetscCall(MatProductSetFill(*C, fill)); 10083 10084 (*C)->product->api_user = PETSC_TRUE; 10085 PetscCall(MatProductSetFromOptions(*C)); 10086 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); 10087 PetscCall(MatProductSymbolic(*C)); 10088 } else { /* scall == MAT_REUSE_MATRIX */ 10089 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10090 } 10091 10092 PetscCall(MatProductNumeric(*C)); 10093 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10094 PetscFunctionReturn(PETSC_SUCCESS); 10095 } 10096 10097 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10098 { 10099 PetscBool flg = PETSC_TRUE; 10100 10101 PetscFunctionBegin; 10102 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10103 if (scall == MAT_INITIAL_MATRIX) { 10104 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10105 PetscCall(MatProductCreate(A, B, NULL, C)); 10106 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10107 PetscCall(MatProductSetFill(*C, fill)); 10108 } else { /* scall == MAT_REUSE_MATRIX */ 10109 Mat_Product *product = (*C)->product; 10110 10111 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10112 if (flg && product && product->type != ptype) { 10113 PetscCall(MatProductClear(*C)); 10114 product = NULL; 10115 } 10116 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10117 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10118 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10119 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10120 product = (*C)->product; 10121 product->fill = fill; 10122 product->clear = PETSC_TRUE; 10123 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10124 flg = PETSC_FALSE; 10125 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10126 } 10127 } 10128 if (flg) { 10129 (*C)->product->api_user = PETSC_TRUE; 10130 PetscCall(MatProductSetType(*C, ptype)); 10131 PetscCall(MatProductSetFromOptions(*C)); 10132 PetscCall(MatProductSymbolic(*C)); 10133 } 10134 PetscCall(MatProductNumeric(*C)); 10135 PetscFunctionReturn(PETSC_SUCCESS); 10136 } 10137 10138 /*@ 10139 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10140 10141 Neighbor-wise Collective 10142 10143 Input Parameters: 10144 + A - the left matrix 10145 . B - the right matrix 10146 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10147 - 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 10148 if the result is a dense matrix this is irrelevant 10149 10150 Output Parameter: 10151 . C - the product matrix 10152 10153 Notes: 10154 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10155 10156 `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 10157 call to this function with `MAT_INITIAL_MATRIX`. 10158 10159 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10160 10161 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`, 10162 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10163 10164 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10165 10166 Example of Usage: 10167 .vb 10168 MatProductCreate(A,B,NULL,&C); 10169 MatProductSetType(C,MATPRODUCT_AB); 10170 MatProductSymbolic(C); 10171 MatProductNumeric(C); // compute C=A * B 10172 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10173 MatProductNumeric(C); 10174 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10175 MatProductNumeric(C); 10176 .ve 10177 10178 Level: intermediate 10179 10180 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10181 @*/ 10182 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10183 { 10184 PetscFunctionBegin; 10185 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10186 PetscFunctionReturn(PETSC_SUCCESS); 10187 } 10188 10189 /*@ 10190 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10191 10192 Neighbor-wise Collective 10193 10194 Input Parameters: 10195 + A - the left matrix 10196 . B - the right matrix 10197 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10198 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10199 10200 Output Parameter: 10201 . C - the product matrix 10202 10203 Options Database Key: 10204 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10205 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10206 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10207 10208 Level: intermediate 10209 10210 Notes: 10211 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10212 10213 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10214 10215 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10216 actually needed. 10217 10218 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10219 and for pairs of `MATMPIDENSE` matrices. 10220 10221 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10222 10223 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10224 10225 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10226 @*/ 10227 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10228 { 10229 PetscFunctionBegin; 10230 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10231 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10232 PetscFunctionReturn(PETSC_SUCCESS); 10233 } 10234 10235 /*@ 10236 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10237 10238 Neighbor-wise Collective 10239 10240 Input Parameters: 10241 + A - the left matrix 10242 . B - the right matrix 10243 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10244 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10245 10246 Output Parameter: 10247 . C - the product matrix 10248 10249 Level: intermediate 10250 10251 Notes: 10252 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10253 10254 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10255 10256 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10257 10258 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10259 actually needed. 10260 10261 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10262 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10263 10264 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10265 10266 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10267 @*/ 10268 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10269 { 10270 PetscFunctionBegin; 10271 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10272 PetscFunctionReturn(PETSC_SUCCESS); 10273 } 10274 10275 /*@ 10276 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10277 10278 Neighbor-wise Collective 10279 10280 Input Parameters: 10281 + A - the left matrix 10282 . B - the middle matrix 10283 . C - the right matrix 10284 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10285 - 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 10286 if the result is a dense matrix this is irrelevant 10287 10288 Output Parameter: 10289 . D - the product matrix 10290 10291 Level: intermediate 10292 10293 Notes: 10294 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10295 10296 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10297 10298 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10299 10300 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10301 actually needed. 10302 10303 If you have many matrices with the same non-zero structure to multiply, you 10304 should use `MAT_REUSE_MATRIX` in all calls but the first 10305 10306 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10307 10308 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10309 @*/ 10310 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10311 { 10312 PetscFunctionBegin; 10313 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10314 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10315 10316 if (scall == MAT_INITIAL_MATRIX) { 10317 PetscCall(MatProductCreate(A, B, C, D)); 10318 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10319 PetscCall(MatProductSetAlgorithm(*D, "default")); 10320 PetscCall(MatProductSetFill(*D, fill)); 10321 10322 (*D)->product->api_user = PETSC_TRUE; 10323 PetscCall(MatProductSetFromOptions(*D)); 10324 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, 10325 ((PetscObject)C)->type_name); 10326 PetscCall(MatProductSymbolic(*D)); 10327 } else { /* user may change input matrices when REUSE */ 10328 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10329 } 10330 PetscCall(MatProductNumeric(*D)); 10331 PetscFunctionReturn(PETSC_SUCCESS); 10332 } 10333 10334 /*@ 10335 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10336 10337 Collective 10338 10339 Input Parameters: 10340 + mat - the matrix 10341 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10342 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10343 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10344 10345 Output Parameter: 10346 . matredundant - redundant matrix 10347 10348 Level: advanced 10349 10350 Notes: 10351 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10352 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10353 10354 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10355 calling it. 10356 10357 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10358 10359 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10360 @*/ 10361 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10362 { 10363 MPI_Comm comm; 10364 PetscMPIInt size; 10365 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10366 Mat_Redundant *redund = NULL; 10367 PetscSubcomm psubcomm = NULL; 10368 MPI_Comm subcomm_in = subcomm; 10369 Mat *matseq; 10370 IS isrow, iscol; 10371 PetscBool newsubcomm = PETSC_FALSE; 10372 10373 PetscFunctionBegin; 10374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10375 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10376 PetscAssertPointer(*matredundant, 5); 10377 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10378 } 10379 10380 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10381 if (size == 1 || nsubcomm == 1) { 10382 if (reuse == MAT_INITIAL_MATRIX) { 10383 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10384 } else { 10385 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"); 10386 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10387 } 10388 PetscFunctionReturn(PETSC_SUCCESS); 10389 } 10390 10391 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10392 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10393 MatCheckPreallocated(mat, 1); 10394 10395 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10396 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10397 /* create psubcomm, then get subcomm */ 10398 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10399 PetscCallMPI(MPI_Comm_size(comm, &size)); 10400 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10401 10402 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10403 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10404 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10405 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10406 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10407 newsubcomm = PETSC_TRUE; 10408 PetscCall(PetscSubcommDestroy(&psubcomm)); 10409 } 10410 10411 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10412 if (reuse == MAT_INITIAL_MATRIX) { 10413 mloc_sub = PETSC_DECIDE; 10414 nloc_sub = PETSC_DECIDE; 10415 if (bs < 1) { 10416 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10417 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10418 } else { 10419 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10420 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10421 } 10422 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10423 rstart = rend - mloc_sub; 10424 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10425 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10426 PetscCall(ISSetIdentity(iscol)); 10427 } else { /* reuse == MAT_REUSE_MATRIX */ 10428 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"); 10429 /* retrieve subcomm */ 10430 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10431 redund = (*matredundant)->redundant; 10432 isrow = redund->isrow; 10433 iscol = redund->iscol; 10434 matseq = redund->matseq; 10435 } 10436 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10437 10438 /* get matredundant over subcomm */ 10439 if (reuse == MAT_INITIAL_MATRIX) { 10440 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10441 10442 /* create a supporting struct and attach it to C for reuse */ 10443 PetscCall(PetscNew(&redund)); 10444 (*matredundant)->redundant = redund; 10445 redund->isrow = isrow; 10446 redund->iscol = iscol; 10447 redund->matseq = matseq; 10448 if (newsubcomm) { 10449 redund->subcomm = subcomm; 10450 } else { 10451 redund->subcomm = MPI_COMM_NULL; 10452 } 10453 } else { 10454 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10455 } 10456 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10457 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10458 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10459 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10460 } 10461 #endif 10462 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10463 PetscFunctionReturn(PETSC_SUCCESS); 10464 } 10465 10466 /*@C 10467 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10468 a given `Mat`. Each submatrix can span multiple procs. 10469 10470 Collective 10471 10472 Input Parameters: 10473 + mat - the matrix 10474 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10475 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10476 10477 Output Parameter: 10478 . subMat - parallel sub-matrices each spanning a given `subcomm` 10479 10480 Level: advanced 10481 10482 Notes: 10483 The submatrix partition across processors is dictated by `subComm` a 10484 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10485 is not restricted to be grouped with consecutive original MPI processes. 10486 10487 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10488 map directly to the layout of the original matrix [wrt the local 10489 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10490 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10491 the `subMat`. However the offDiagMat looses some columns - and this is 10492 reconstructed with `MatSetValues()` 10493 10494 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10495 10496 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10497 @*/ 10498 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10499 { 10500 PetscMPIInt commsize, subCommSize; 10501 10502 PetscFunctionBegin; 10503 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10504 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10505 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10506 10507 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"); 10508 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10509 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10510 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10511 PetscFunctionReturn(PETSC_SUCCESS); 10512 } 10513 10514 /*@ 10515 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10516 10517 Not Collective 10518 10519 Input Parameters: 10520 + mat - matrix to extract local submatrix from 10521 . isrow - local row indices for submatrix 10522 - iscol - local column indices for submatrix 10523 10524 Output Parameter: 10525 . submat - the submatrix 10526 10527 Level: intermediate 10528 10529 Notes: 10530 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10531 10532 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10533 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10534 10535 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10536 `MatSetValuesBlockedLocal()` will also be implemented. 10537 10538 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10539 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10540 10541 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10542 @*/ 10543 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10544 { 10545 PetscFunctionBegin; 10546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10547 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10548 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10549 PetscCheckSameComm(isrow, 2, iscol, 3); 10550 PetscAssertPointer(submat, 4); 10551 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10552 10553 if (mat->ops->getlocalsubmatrix) { 10554 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10555 } else { 10556 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10557 } 10558 PetscFunctionReturn(PETSC_SUCCESS); 10559 } 10560 10561 /*@ 10562 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10563 10564 Not Collective 10565 10566 Input Parameters: 10567 + mat - matrix to extract local submatrix from 10568 . isrow - local row indices for submatrix 10569 . iscol - local column indices for submatrix 10570 - submat - the submatrix 10571 10572 Level: intermediate 10573 10574 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10575 @*/ 10576 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10577 { 10578 PetscFunctionBegin; 10579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10580 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10581 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10582 PetscCheckSameComm(isrow, 2, iscol, 3); 10583 PetscAssertPointer(submat, 4); 10584 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10585 10586 if (mat->ops->restorelocalsubmatrix) { 10587 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10588 } else { 10589 PetscCall(MatDestroy(submat)); 10590 } 10591 *submat = NULL; 10592 PetscFunctionReturn(PETSC_SUCCESS); 10593 } 10594 10595 /*@ 10596 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10597 10598 Collective 10599 10600 Input Parameter: 10601 . mat - the matrix 10602 10603 Output Parameter: 10604 . is - if any rows have zero diagonals this contains the list of them 10605 10606 Level: developer 10607 10608 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10609 @*/ 10610 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10611 { 10612 PetscFunctionBegin; 10613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10614 PetscValidType(mat, 1); 10615 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10616 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10617 10618 if (!mat->ops->findzerodiagonals) { 10619 Vec diag; 10620 const PetscScalar *a; 10621 PetscInt *rows; 10622 PetscInt rStart, rEnd, r, nrow = 0; 10623 10624 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10625 PetscCall(MatGetDiagonal(mat, diag)); 10626 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10627 PetscCall(VecGetArrayRead(diag, &a)); 10628 for (r = 0; r < rEnd - rStart; ++r) 10629 if (a[r] == 0.0) ++nrow; 10630 PetscCall(PetscMalloc1(nrow, &rows)); 10631 nrow = 0; 10632 for (r = 0; r < rEnd - rStart; ++r) 10633 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10634 PetscCall(VecRestoreArrayRead(diag, &a)); 10635 PetscCall(VecDestroy(&diag)); 10636 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10637 } else { 10638 PetscUseTypeMethod(mat, findzerodiagonals, is); 10639 } 10640 PetscFunctionReturn(PETSC_SUCCESS); 10641 } 10642 10643 /*@ 10644 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10645 10646 Collective 10647 10648 Input Parameter: 10649 . mat - the matrix 10650 10651 Output Parameter: 10652 . is - contains the list of rows with off block diagonal entries 10653 10654 Level: developer 10655 10656 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10657 @*/ 10658 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10659 { 10660 PetscFunctionBegin; 10661 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10662 PetscValidType(mat, 1); 10663 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10664 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10665 10666 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10667 PetscFunctionReturn(PETSC_SUCCESS); 10668 } 10669 10670 /*@C 10671 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10672 10673 Collective; No Fortran Support 10674 10675 Input Parameter: 10676 . mat - the matrix 10677 10678 Output Parameter: 10679 . values - the block inverses in column major order (FORTRAN-like) 10680 10681 Level: advanced 10682 10683 Notes: 10684 The size of the blocks is determined by the block size of the matrix. 10685 10686 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10687 10688 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10689 10690 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10691 @*/ 10692 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10693 { 10694 PetscFunctionBegin; 10695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10696 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10697 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10698 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10699 PetscFunctionReturn(PETSC_SUCCESS); 10700 } 10701 10702 /*@ 10703 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10704 10705 Collective; No Fortran Support 10706 10707 Input Parameters: 10708 + mat - the matrix 10709 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10710 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10711 10712 Output Parameter: 10713 . values - the block inverses in column major order (FORTRAN-like) 10714 10715 Level: advanced 10716 10717 Notes: 10718 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10719 10720 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10721 10722 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10723 @*/ 10724 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10725 { 10726 PetscFunctionBegin; 10727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10728 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10729 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10730 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10731 PetscFunctionReturn(PETSC_SUCCESS); 10732 } 10733 10734 /*@ 10735 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10736 10737 Collective 10738 10739 Input Parameters: 10740 + A - the matrix 10741 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10742 10743 Level: advanced 10744 10745 Note: 10746 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10747 10748 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10749 @*/ 10750 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10751 { 10752 const PetscScalar *vals; 10753 PetscInt *dnnz; 10754 PetscInt m, rstart, rend, bs, i, j; 10755 10756 PetscFunctionBegin; 10757 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10758 PetscCall(MatGetBlockSize(A, &bs)); 10759 PetscCall(MatGetLocalSize(A, &m, NULL)); 10760 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10761 if (A->rmap->bs > 1) PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); // mpiaij to A and B 10762 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10763 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10764 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10765 PetscCall(PetscFree(dnnz)); 10766 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10767 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10768 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10769 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10770 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10771 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10772 PetscFunctionReturn(PETSC_SUCCESS); 10773 } 10774 10775 /*@ 10776 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10777 via `MatTransposeColoringCreate()`. 10778 10779 Collective 10780 10781 Input Parameter: 10782 . c - coloring context 10783 10784 Level: intermediate 10785 10786 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10787 @*/ 10788 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10789 { 10790 MatTransposeColoring matcolor = *c; 10791 10792 PetscFunctionBegin; 10793 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10794 if (--((PetscObject)matcolor)->refct > 0) { 10795 matcolor = NULL; 10796 PetscFunctionReturn(PETSC_SUCCESS); 10797 } 10798 10799 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10800 PetscCall(PetscFree(matcolor->rows)); 10801 PetscCall(PetscFree(matcolor->den2sp)); 10802 PetscCall(PetscFree(matcolor->colorforcol)); 10803 PetscCall(PetscFree(matcolor->columns)); 10804 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10805 PetscCall(PetscHeaderDestroy(c)); 10806 PetscFunctionReturn(PETSC_SUCCESS); 10807 } 10808 10809 /*@ 10810 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10811 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10812 `MatTransposeColoring` to sparse `B`. 10813 10814 Collective 10815 10816 Input Parameters: 10817 + coloring - coloring context created with `MatTransposeColoringCreate()` 10818 - B - sparse matrix 10819 10820 Output Parameter: 10821 . Btdense - dense matrix $B^T$ 10822 10823 Level: developer 10824 10825 Note: 10826 These are used internally for some implementations of `MatRARt()` 10827 10828 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10829 @*/ 10830 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10831 { 10832 PetscFunctionBegin; 10833 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10834 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10835 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10836 10837 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10838 PetscFunctionReturn(PETSC_SUCCESS); 10839 } 10840 10841 /*@ 10842 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10843 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10844 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10845 $C_{sp}$ from $C_{den}$. 10846 10847 Collective 10848 10849 Input Parameters: 10850 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10851 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10852 10853 Output Parameter: 10854 . Csp - sparse matrix 10855 10856 Level: developer 10857 10858 Note: 10859 These are used internally for some implementations of `MatRARt()` 10860 10861 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10862 @*/ 10863 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10864 { 10865 PetscFunctionBegin; 10866 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10867 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10868 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10869 10870 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10871 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10872 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10873 PetscFunctionReturn(PETSC_SUCCESS); 10874 } 10875 10876 /*@ 10877 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10878 10879 Collective 10880 10881 Input Parameters: 10882 + mat - the matrix product C 10883 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10884 10885 Output Parameter: 10886 . color - the new coloring context 10887 10888 Level: intermediate 10889 10890 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10891 `MatTransColoringApplyDenToSp()` 10892 @*/ 10893 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10894 { 10895 MatTransposeColoring c; 10896 MPI_Comm comm; 10897 10898 PetscFunctionBegin; 10899 PetscAssertPointer(color, 3); 10900 10901 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10902 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10903 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10904 c->ctype = iscoloring->ctype; 10905 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10906 *color = c; 10907 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10908 PetscFunctionReturn(PETSC_SUCCESS); 10909 } 10910 10911 /*@ 10912 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10913 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10914 10915 Not Collective 10916 10917 Input Parameter: 10918 . mat - the matrix 10919 10920 Output Parameter: 10921 . state - the current state 10922 10923 Level: intermediate 10924 10925 Notes: 10926 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10927 different matrices 10928 10929 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10930 10931 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10932 10933 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10934 @*/ 10935 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10936 { 10937 PetscFunctionBegin; 10938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10939 *state = mat->nonzerostate; 10940 PetscFunctionReturn(PETSC_SUCCESS); 10941 } 10942 10943 /*@ 10944 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10945 matrices from each processor 10946 10947 Collective 10948 10949 Input Parameters: 10950 + comm - the communicators the parallel matrix will live on 10951 . seqmat - the input sequential matrices 10952 . n - number of local columns (or `PETSC_DECIDE`) 10953 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10954 10955 Output Parameter: 10956 . mpimat - the parallel matrix generated 10957 10958 Level: developer 10959 10960 Note: 10961 The number of columns of the matrix in EACH processor MUST be the same. 10962 10963 .seealso: [](ch_matrices), `Mat` 10964 @*/ 10965 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10966 { 10967 PetscMPIInt size; 10968 10969 PetscFunctionBegin; 10970 PetscCallMPI(MPI_Comm_size(comm, &size)); 10971 if (size == 1) { 10972 if (reuse == MAT_INITIAL_MATRIX) { 10973 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10974 } else { 10975 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10976 } 10977 PetscFunctionReturn(PETSC_SUCCESS); 10978 } 10979 10980 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"); 10981 10982 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10983 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10984 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10985 PetscFunctionReturn(PETSC_SUCCESS); 10986 } 10987 10988 /*@ 10989 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10990 10991 Collective 10992 10993 Input Parameters: 10994 + A - the matrix to create subdomains from 10995 - N - requested number of subdomains 10996 10997 Output Parameters: 10998 + n - number of subdomains resulting on this MPI process 10999 - iss - `IS` list with indices of subdomains on this MPI process 11000 11001 Level: advanced 11002 11003 Note: 11004 The number of subdomains must be smaller than the communicator size 11005 11006 .seealso: [](ch_matrices), `Mat`, `IS` 11007 @*/ 11008 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11009 { 11010 MPI_Comm comm, subcomm; 11011 PetscMPIInt size, rank, color; 11012 PetscInt rstart, rend, k; 11013 11014 PetscFunctionBegin; 11015 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11016 PetscCallMPI(MPI_Comm_size(comm, &size)); 11017 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11018 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); 11019 *n = 1; 11020 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11021 color = rank / k; 11022 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11023 PetscCall(PetscMalloc1(1, iss)); 11024 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11025 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11026 PetscCallMPI(MPI_Comm_free(&subcomm)); 11027 PetscFunctionReturn(PETSC_SUCCESS); 11028 } 11029 11030 /*@ 11031 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11032 11033 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11034 If they are not the same, uses `MatMatMatMult()`. 11035 11036 Once the coarse grid problem is constructed, correct for interpolation operators 11037 that are not of full rank, which can legitimately happen in the case of non-nested 11038 geometric multigrid. 11039 11040 Input Parameters: 11041 + restrct - restriction operator 11042 . dA - fine grid matrix 11043 . interpolate - interpolation operator 11044 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11045 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11046 11047 Output Parameter: 11048 . A - the Galerkin coarse matrix 11049 11050 Options Database Key: 11051 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11052 11053 Level: developer 11054 11055 Note: 11056 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11057 11058 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11059 @*/ 11060 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11061 { 11062 IS zerorows; 11063 Vec diag; 11064 11065 PetscFunctionBegin; 11066 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11067 /* Construct the coarse grid matrix */ 11068 if (interpolate == restrct) { 11069 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11070 } else { 11071 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11072 } 11073 11074 /* If the interpolation matrix is not of full rank, A will have zero rows. 11075 This can legitimately happen in the case of non-nested geometric multigrid. 11076 In that event, we set the rows of the matrix to the rows of the identity, 11077 ignoring the equations (as the RHS will also be zero). */ 11078 11079 PetscCall(MatFindZeroRows(*A, &zerorows)); 11080 11081 if (zerorows != NULL) { /* if there are any zero rows */ 11082 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11083 PetscCall(MatGetDiagonal(*A, diag)); 11084 PetscCall(VecISSet(diag, zerorows, 1.0)); 11085 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11086 PetscCall(VecDestroy(&diag)); 11087 PetscCall(ISDestroy(&zerorows)); 11088 } 11089 PetscFunctionReturn(PETSC_SUCCESS); 11090 } 11091 11092 /*@C 11093 MatSetOperation - Allows user to set a matrix operation for any matrix type 11094 11095 Logically Collective 11096 11097 Input Parameters: 11098 + mat - the matrix 11099 . op - the name of the operation 11100 - f - the function that provides the operation 11101 11102 Level: developer 11103 11104 Example Usage: 11105 .vb 11106 extern PetscErrorCode usermult(Mat, Vec, Vec); 11107 11108 PetscCall(MatCreateXXX(comm, ..., &A)); 11109 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11110 .ve 11111 11112 Notes: 11113 See the file `include/petscmat.h` for a complete list of matrix 11114 operations, which all have the form MATOP_<OPERATION>, where 11115 <OPERATION> is the name (in all capital letters) of the 11116 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11117 11118 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11119 sequence as the usual matrix interface routines, since they 11120 are intended to be accessed via the usual matrix interface 11121 routines, e.g., 11122 .vb 11123 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11124 .ve 11125 11126 In particular each function MUST return `PETSC_SUCCESS` on success and 11127 nonzero on failure. 11128 11129 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11130 11131 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11132 @*/ 11133 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11134 { 11135 PetscFunctionBegin; 11136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11137 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11138 (((void (**)(void))mat->ops)[op]) = f; 11139 PetscFunctionReturn(PETSC_SUCCESS); 11140 } 11141 11142 /*@C 11143 MatGetOperation - Gets a matrix operation for any matrix type. 11144 11145 Not Collective 11146 11147 Input Parameters: 11148 + mat - the matrix 11149 - op - the name of the operation 11150 11151 Output Parameter: 11152 . f - the function that provides the operation 11153 11154 Level: developer 11155 11156 Example Usage: 11157 .vb 11158 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11159 11160 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11161 .ve 11162 11163 Notes: 11164 See the file include/petscmat.h for a complete list of matrix 11165 operations, which all have the form MATOP_<OPERATION>, where 11166 <OPERATION> is the name (in all capital letters) of the 11167 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11168 11169 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11170 11171 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11172 @*/ 11173 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11174 { 11175 PetscFunctionBegin; 11176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11177 *f = (((void (**)(void))mat->ops)[op]); 11178 PetscFunctionReturn(PETSC_SUCCESS); 11179 } 11180 11181 /*@ 11182 MatHasOperation - Determines whether the given matrix supports the particular operation. 11183 11184 Not Collective 11185 11186 Input Parameters: 11187 + mat - the matrix 11188 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11189 11190 Output Parameter: 11191 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11192 11193 Level: advanced 11194 11195 Note: 11196 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11197 11198 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11199 @*/ 11200 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11201 { 11202 PetscFunctionBegin; 11203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11204 PetscAssertPointer(has, 3); 11205 if (mat->ops->hasoperation) { 11206 PetscUseTypeMethod(mat, hasoperation, op, has); 11207 } else { 11208 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11209 else { 11210 *has = PETSC_FALSE; 11211 if (op == MATOP_CREATE_SUBMATRIX) { 11212 PetscMPIInt size; 11213 11214 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11215 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11216 } 11217 } 11218 } 11219 PetscFunctionReturn(PETSC_SUCCESS); 11220 } 11221 11222 /*@ 11223 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11224 11225 Collective 11226 11227 Input Parameter: 11228 . mat - the matrix 11229 11230 Output Parameter: 11231 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11232 11233 Level: beginner 11234 11235 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11236 @*/ 11237 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11238 { 11239 PetscFunctionBegin; 11240 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11241 PetscValidType(mat, 1); 11242 PetscAssertPointer(cong, 2); 11243 if (!mat->rmap || !mat->cmap) { 11244 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11245 PetscFunctionReturn(PETSC_SUCCESS); 11246 } 11247 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11248 PetscCall(PetscLayoutSetUp(mat->rmap)); 11249 PetscCall(PetscLayoutSetUp(mat->cmap)); 11250 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11251 if (*cong) mat->congruentlayouts = 1; 11252 else mat->congruentlayouts = 0; 11253 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11254 PetscFunctionReturn(PETSC_SUCCESS); 11255 } 11256 11257 PetscErrorCode MatSetInf(Mat A) 11258 { 11259 PetscFunctionBegin; 11260 PetscUseTypeMethod(A, setinf); 11261 PetscFunctionReturn(PETSC_SUCCESS); 11262 } 11263 11264 /*@ 11265 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 11266 and possibly removes small values from the graph structure. 11267 11268 Collective 11269 11270 Input Parameters: 11271 + A - the matrix 11272 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11273 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11274 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11275 . num_idx - size of 'index' array 11276 - index - array of block indices to use for graph strength of connection weight 11277 11278 Output Parameter: 11279 . graph - the resulting graph 11280 11281 Level: advanced 11282 11283 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11284 @*/ 11285 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11286 { 11287 PetscFunctionBegin; 11288 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11289 PetscValidType(A, 1); 11290 PetscValidLogicalCollectiveBool(A, scale, 3); 11291 PetscAssertPointer(graph, 7); 11292 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11293 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11294 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11295 PetscFunctionReturn(PETSC_SUCCESS); 11296 } 11297 11298 /*@ 11299 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11300 meaning the same memory is used for the matrix, and no new memory is allocated. 11301 11302 Collective 11303 11304 Input Parameters: 11305 + A - the matrix 11306 - 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 11307 11308 Level: intermediate 11309 11310 Developer Note: 11311 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11312 of the arrays in the data structure are unneeded. 11313 11314 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11315 @*/ 11316 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11317 { 11318 PetscFunctionBegin; 11319 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11320 PetscUseTypeMethod(A, eliminatezeros, keep); 11321 PetscFunctionReturn(PETSC_SUCCESS); 11322 } 11323