1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscFunctionReturn(PETSC_SUCCESS); 759 } 760 761 /*@ 762 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 763 for matrices created with `MatGetFactor()` 764 765 Logically Collective 766 767 Input Parameters: 768 + A - the matrix 769 - prefix - the prefix to prepend to all option names for the factored matrix 770 771 Level: developer 772 773 Notes: 774 A hyphen (-) must NOT be given at the beginning of the prefix name. 775 The first character of all runtime options is AUTOMATICALLY the hyphen. 776 777 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 778 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 779 780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 781 @*/ 782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 783 { 784 PetscFunctionBegin; 785 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 786 if (prefix) { 787 PetscAssertPointer(prefix, 2); 788 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 789 if (prefix != A->factorprefix) { 790 PetscCall(PetscFree(A->factorprefix)); 791 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 792 } 793 } else PetscCall(PetscFree(A->factorprefix)); 794 PetscFunctionReturn(PETSC_SUCCESS); 795 } 796 797 /*@ 798 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 799 for matrices created with `MatGetFactor()` 800 801 Logically Collective 802 803 Input Parameters: 804 + A - the matrix 805 - prefix - the prefix to prepend to all option names for the factored matrix 806 807 Level: developer 808 809 Notes: 810 A hyphen (-) must NOT be given at the beginning of the prefix name. 811 The first character of all runtime options is AUTOMATICALLY the hyphen. 812 813 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 814 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 815 816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 817 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 818 `MatSetOptionsPrefix()` 819 @*/ 820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 821 { 822 size_t len1, len2, new_len; 823 824 PetscFunctionBegin; 825 PetscValidHeader(A, 1); 826 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 827 if (!A->factorprefix) { 828 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 829 PetscFunctionReturn(PETSC_SUCCESS); 830 } 831 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 832 833 PetscCall(PetscStrlen(A->factorprefix, &len1)); 834 PetscCall(PetscStrlen(prefix, &len2)); 835 new_len = len1 + len2 + 1; 836 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 837 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@ 842 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 843 matrix options in the database. 844 845 Logically Collective 846 847 Input Parameters: 848 + A - the matrix 849 - prefix - the prefix to prepend to all option names 850 851 Level: advanced 852 853 Note: 854 A hyphen (-) must NOT be given at the beginning of the prefix name. 855 The first character of all runtime options is AUTOMATICALLY the hyphen. 856 857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 858 @*/ 859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 860 { 861 PetscFunctionBegin; 862 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 863 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 864 PetscFunctionReturn(PETSC_SUCCESS); 865 } 866 867 /*@ 868 MatGetOptionsPrefix - Gets the prefix used for searching for all 869 matrix options in the database. 870 871 Not Collective 872 873 Input Parameter: 874 . A - the matrix 875 876 Output Parameter: 877 . prefix - pointer to the prefix string used 878 879 Level: advanced 880 881 Fortran Note: 882 The user should pass in a string `prefix` of 883 sufficient length to hold the prefix. 884 885 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 886 @*/ 887 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 888 { 889 PetscFunctionBegin; 890 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 891 PetscAssertPointer(prefix, 2); 892 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 893 PetscFunctionReturn(PETSC_SUCCESS); 894 } 895 896 /*@ 897 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 898 899 Not Collective 900 901 Input Parameter: 902 . A - the matrix 903 904 Output Parameter: 905 . state - the object state 906 907 Level: advanced 908 909 Note: 910 Object state is an integer which gets increased every time 911 the object is changed. By saving and later querying the object state 912 one can determine whether information about the object is still current. 913 914 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 915 916 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 917 @*/ 918 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 919 { 920 PetscFunctionBegin; 921 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 922 PetscAssertPointer(state, 2); 923 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 924 PetscFunctionReturn(PETSC_SUCCESS); 925 } 926 927 /*@ 928 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 929 930 Collective 931 932 Input Parameter: 933 . A - the matrix 934 935 Level: beginner 936 937 Notes: 938 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 939 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 940 makes all of the preallocation space available 941 942 Current values in the matrix are lost in this call. 943 944 Currently only supported for `MATAIJ` matrices. 945 946 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 947 @*/ 948 PetscErrorCode MatResetPreallocation(Mat A) 949 { 950 PetscFunctionBegin; 951 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 952 PetscValidType(A, 1); 953 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()"); 954 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 955 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 956 PetscFunctionReturn(PETSC_SUCCESS); 957 } 958 959 /*@ 960 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 961 962 Collective 963 964 Input Parameter: 965 . A - the matrix 966 967 Level: intermediate 968 969 Notes: 970 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 971 972 Currently only supported for `MATAIJ` matrices. 973 974 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 975 @*/ 976 PetscErrorCode MatResetHash(Mat A) 977 { 978 PetscFunctionBegin; 979 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 980 PetscValidType(A, 1); 981 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()"); 982 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 983 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 984 /* These flags are used to determine whether certain setups occur */ 985 A->was_assembled = PETSC_FALSE; 986 A->assembled = PETSC_FALSE; 987 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 988 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 989 PetscFunctionReturn(PETSC_SUCCESS); 990 } 991 992 /*@ 993 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 994 995 Collective 996 997 Input Parameter: 998 . A - the matrix 999 1000 Level: advanced 1001 1002 Notes: 1003 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1004 setting values in the matrix. 1005 1006 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1007 1008 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1009 @*/ 1010 PetscErrorCode MatSetUp(Mat A) 1011 { 1012 PetscFunctionBegin; 1013 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1014 if (!((PetscObject)A)->type_name) { 1015 PetscMPIInt size; 1016 1017 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1018 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1019 } 1020 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1021 PetscCall(PetscLayoutSetUp(A->rmap)); 1022 PetscCall(PetscLayoutSetUp(A->cmap)); 1023 A->preallocated = PETSC_TRUE; 1024 PetscFunctionReturn(PETSC_SUCCESS); 1025 } 1026 1027 #if defined(PETSC_HAVE_SAWS) 1028 #include <petscviewersaws.h> 1029 #endif 1030 1031 /* 1032 If threadsafety is on extraneous matrices may be printed 1033 1034 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1035 */ 1036 #if !defined(PETSC_HAVE_THREADSAFETY) 1037 static PetscInt insidematview = 0; 1038 #endif 1039 1040 /*@ 1041 MatViewFromOptions - View properties of the matrix based on options set in the options database 1042 1043 Collective 1044 1045 Input Parameters: 1046 + A - the matrix 1047 . obj - optional additional object that provides the options prefix to use 1048 - name - command line option 1049 1050 Options Database Key: 1051 . -mat_view [viewertype]:... - the viewer and its options 1052 1053 Level: intermediate 1054 1055 Note: 1056 .vb 1057 If no value is provided ascii:stdout is used 1058 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1059 for example ascii::ascii_info prints just the information about the object not all details 1060 unless :append is given filename opens in write mode, overwriting what was already there 1061 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1062 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1063 socket[:port] defaults to the standard output port 1064 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1065 .ve 1066 1067 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1068 @*/ 1069 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1070 { 1071 PetscFunctionBegin; 1072 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1073 #if !defined(PETSC_HAVE_THREADSAFETY) 1074 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1075 #endif 1076 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1077 PetscFunctionReturn(PETSC_SUCCESS); 1078 } 1079 1080 /*@ 1081 MatView - display information about a matrix in a variety ways 1082 1083 Collective on viewer 1084 1085 Input Parameters: 1086 + mat - the matrix 1087 - viewer - visualization context 1088 1089 Options Database Keys: 1090 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1091 . -mat_view ::ascii_info_detail - Prints more detailed info 1092 . -mat_view - Prints matrix in ASCII format 1093 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1094 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1095 . -display <name> - Sets display name (default is host) 1096 . -draw_pause <sec> - Sets number of seconds to pause after display 1097 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1098 . -viewer_socket_machine <machine> - - 1099 . -viewer_socket_port <port> - - 1100 . -mat_view binary - save matrix to file in binary format 1101 - -viewer_binary_filename <name> - - 1102 1103 Level: beginner 1104 1105 Notes: 1106 The available visualization contexts include 1107 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1108 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1109 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1110 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1111 1112 The user can open alternative visualization contexts with 1113 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1114 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1115 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1116 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1117 1118 The user can call `PetscViewerPushFormat()` to specify the output 1119 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1120 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1121 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1122 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1123 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1124 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1125 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1126 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1127 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1128 1129 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1130 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1131 1132 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1133 1134 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1135 viewer is used. 1136 1137 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1138 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1139 1140 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1141 and then use the following mouse functions. 1142 .vb 1143 left mouse: zoom in 1144 middle mouse: zoom out 1145 right mouse: continue with the simulation 1146 .ve 1147 1148 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1149 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1150 @*/ 1151 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1152 { 1153 PetscInt rows, cols, rbs, cbs; 1154 PetscBool isascii, isstring, issaws; 1155 PetscViewerFormat format; 1156 PetscMPIInt size; 1157 1158 PetscFunctionBegin; 1159 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1160 PetscValidType(mat, 1); 1161 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1162 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1163 1164 PetscCall(PetscViewerGetFormat(viewer, &format)); 1165 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1166 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1167 1168 #if !defined(PETSC_HAVE_THREADSAFETY) 1169 insidematview++; 1170 #endif 1171 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1172 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1173 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1174 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"); 1175 1176 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1177 if (isascii) { 1178 if (!mat->preallocated) { 1179 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1180 #if !defined(PETSC_HAVE_THREADSAFETY) 1181 insidematview--; 1182 #endif 1183 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1184 PetscFunctionReturn(PETSC_SUCCESS); 1185 } 1186 if (!mat->assembled) { 1187 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1188 #if !defined(PETSC_HAVE_THREADSAFETY) 1189 insidematview--; 1190 #endif 1191 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1192 PetscFunctionReturn(PETSC_SUCCESS); 1193 } 1194 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1195 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1196 MatNullSpace nullsp, transnullsp; 1197 1198 PetscCall(PetscViewerASCIIPushTab(viewer)); 1199 PetscCall(MatGetSize(mat, &rows, &cols)); 1200 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1201 if (rbs != 1 || cbs != 1) { 1202 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" : "")); 1203 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1204 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1205 if (mat->factortype) { 1206 MatSolverType solver; 1207 PetscCall(MatFactorGetSolverType(mat, &solver)); 1208 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1209 } 1210 if (mat->ops->getinfo) { 1211 MatInfo info; 1212 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1213 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1214 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1215 } 1216 PetscCall(MatGetNullSpace(mat, &nullsp)); 1217 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1218 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1219 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1220 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1221 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1222 PetscCall(PetscViewerASCIIPushTab(viewer)); 1223 PetscCall(MatProductView(mat, viewer)); 1224 PetscCall(PetscViewerASCIIPopTab(viewer)); 1225 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1226 IS tmp; 1227 1228 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1229 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1230 PetscCall(PetscViewerASCIIPushTab(viewer)); 1231 PetscCall(ISView(tmp, viewer)); 1232 PetscCall(PetscViewerASCIIPopTab(viewer)); 1233 PetscCall(ISDestroy(&tmp)); 1234 } 1235 } 1236 } else if (issaws) { 1237 #if defined(PETSC_HAVE_SAWS) 1238 PetscMPIInt rank; 1239 1240 PetscCall(PetscObjectName((PetscObject)mat)); 1241 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1242 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1243 #endif 1244 } else if (isstring) { 1245 const char *type; 1246 PetscCall(MatGetType(mat, &type)); 1247 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1248 PetscTryTypeMethod(mat, view, viewer); 1249 } 1250 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1251 PetscCall(PetscViewerASCIIPushTab(viewer)); 1252 PetscUseTypeMethod(mat, viewnative, viewer); 1253 PetscCall(PetscViewerASCIIPopTab(viewer)); 1254 } else if (mat->ops->view) { 1255 PetscCall(PetscViewerASCIIPushTab(viewer)); 1256 PetscUseTypeMethod(mat, view, viewer); 1257 PetscCall(PetscViewerASCIIPopTab(viewer)); 1258 } 1259 if (isascii) { 1260 PetscCall(PetscViewerGetFormat(viewer, &format)); 1261 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1262 } 1263 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1264 #if !defined(PETSC_HAVE_THREADSAFETY) 1265 insidematview--; 1266 #endif 1267 PetscFunctionReturn(PETSC_SUCCESS); 1268 } 1269 1270 #if defined(PETSC_USE_DEBUG) 1271 #include <../src/sys/totalview/tv_data_display.h> 1272 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1273 { 1274 TV_add_row("Local rows", "int", &mat->rmap->n); 1275 TV_add_row("Local columns", "int", &mat->cmap->n); 1276 TV_add_row("Global rows", "int", &mat->rmap->N); 1277 TV_add_row("Global columns", "int", &mat->cmap->N); 1278 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1279 return TV_format_OK; 1280 } 1281 #endif 1282 1283 /*@ 1284 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1285 with `MatView()`. The matrix format is determined from the options database. 1286 Generates a parallel MPI matrix if the communicator has more than one 1287 processor. The default matrix type is `MATAIJ`. 1288 1289 Collective 1290 1291 Input Parameters: 1292 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1293 or some related function before a call to `MatLoad()` 1294 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1295 1296 Options Database Key: 1297 . -matload_block_size <bs> - set block size 1298 1299 Level: beginner 1300 1301 Notes: 1302 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1303 `Mat` before calling this routine if you wish to set it from the options database. 1304 1305 `MatLoad()` automatically loads into the options database any options 1306 given in the file filename.info where filename is the name of the file 1307 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1308 file will be ignored if you use the -viewer_binary_skip_info option. 1309 1310 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1311 sets the default matrix type AIJ and sets the local and global sizes. 1312 If type and/or size is already set, then the same are used. 1313 1314 In parallel, each processor can load a subset of rows (or the 1315 entire matrix). This routine is especially useful when a large 1316 matrix is stored on disk and only part of it is desired on each 1317 processor. For example, a parallel solver may access only some of 1318 the rows from each processor. The algorithm used here reads 1319 relatively small blocks of data rather than reading the entire 1320 matrix and then subsetting it. 1321 1322 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1323 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1324 or the sequence like 1325 .vb 1326 `PetscViewer` v; 1327 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1328 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1329 `PetscViewerSetFromOptions`(v); 1330 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1331 `PetscViewerFileSetName`(v,"datafile"); 1332 .ve 1333 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1334 $ -viewer_type {binary, hdf5} 1335 1336 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1337 and src/mat/tutorials/ex10.c with the second approach. 1338 1339 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1340 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1341 Multiple objects, both matrices and vectors, can be stored within the same file. 1342 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1343 1344 Most users should not need to know the details of the binary storage 1345 format, since `MatLoad()` and `MatView()` completely hide these details. 1346 But for anyone who is interested, the standard binary matrix storage 1347 format is 1348 1349 .vb 1350 PetscInt MAT_FILE_CLASSID 1351 PetscInt number of rows 1352 PetscInt number of columns 1353 PetscInt total number of nonzeros 1354 PetscInt *number nonzeros in each row 1355 PetscInt *column indices of all nonzeros (starting index is zero) 1356 PetscScalar *values of all nonzeros 1357 .ve 1358 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1359 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 1360 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1361 1362 PETSc automatically does the byte swapping for 1363 machines that store the bytes reversed. Thus if you write your own binary 1364 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1365 and `PetscBinaryWrite()` to see how this may be done. 1366 1367 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1368 Each processor's chunk is loaded independently by its owning MPI process. 1369 Multiple objects, both matrices and vectors, can be stored within the same file. 1370 They are looked up by their PetscObject name. 1371 1372 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1373 by default the same structure and naming of the AIJ arrays and column count 1374 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1375 $ save example.mat A b -v7.3 1376 can be directly read by this routine (see Reference 1 for details). 1377 1378 Depending on your MATLAB version, this format might be a default, 1379 otherwise you can set it as default in Preferences. 1380 1381 Unless -nocompression flag is used to save the file in MATLAB, 1382 PETSc must be configured with ZLIB package. 1383 1384 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1385 1386 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1387 1388 Corresponding `MatView()` is not yet implemented. 1389 1390 The loaded matrix is actually a transpose of the original one in MATLAB, 1391 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1392 With this format, matrix is automatically transposed by PETSc, 1393 unless the matrix is marked as SPD or symmetric 1394 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1395 1396 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1397 1398 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1399 @*/ 1400 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1401 { 1402 PetscBool flg; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1406 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1407 1408 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1409 1410 flg = PETSC_FALSE; 1411 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1412 if (flg) { 1413 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1414 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1415 } 1416 flg = PETSC_FALSE; 1417 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1418 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1419 1420 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1421 PetscUseTypeMethod(mat, load, viewer); 1422 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1423 PetscFunctionReturn(PETSC_SUCCESS); 1424 } 1425 1426 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1427 { 1428 Mat_Redundant *redund = *redundant; 1429 1430 PetscFunctionBegin; 1431 if (redund) { 1432 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1433 PetscCall(ISDestroy(&redund->isrow)); 1434 PetscCall(ISDestroy(&redund->iscol)); 1435 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1436 } else { 1437 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1438 PetscCall(PetscFree(redund->sbuf_j)); 1439 PetscCall(PetscFree(redund->sbuf_a)); 1440 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1441 PetscCall(PetscFree(redund->rbuf_j[i])); 1442 PetscCall(PetscFree(redund->rbuf_a[i])); 1443 } 1444 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1445 } 1446 1447 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1448 PetscCall(PetscFree(redund)); 1449 } 1450 PetscFunctionReturn(PETSC_SUCCESS); 1451 } 1452 1453 /*@ 1454 MatDestroy - Frees space taken by a matrix. 1455 1456 Collective 1457 1458 Input Parameter: 1459 . A - the matrix 1460 1461 Level: beginner 1462 1463 Developer Note: 1464 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1465 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1466 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1467 if changes are needed here. 1468 1469 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1470 @*/ 1471 PetscErrorCode MatDestroy(Mat *A) 1472 { 1473 PetscFunctionBegin; 1474 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1475 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1476 if (--((PetscObject)*A)->refct > 0) { 1477 *A = NULL; 1478 PetscFunctionReturn(PETSC_SUCCESS); 1479 } 1480 1481 /* if memory was published with SAWs then destroy it */ 1482 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1483 PetscTryTypeMethod(*A, destroy); 1484 1485 PetscCall(PetscFree((*A)->factorprefix)); 1486 PetscCall(PetscFree((*A)->defaultvectype)); 1487 PetscCall(PetscFree((*A)->defaultrandtype)); 1488 PetscCall(PetscFree((*A)->bsizes)); 1489 PetscCall(PetscFree((*A)->solvertype)); 1490 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1491 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1492 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1493 PetscCall(MatProductClear(*A)); 1494 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1495 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1496 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1497 PetscCall(MatDestroy(&(*A)->schur)); 1498 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1499 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1500 PetscCall(PetscHeaderDestroy(A)); 1501 PetscFunctionReturn(PETSC_SUCCESS); 1502 } 1503 1504 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1505 /*@ 1506 MatSetValues - Inserts or adds a block of values into a matrix. 1507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1508 MUST be called after all calls to `MatSetValues()` have been completed. 1509 1510 Not Collective 1511 1512 Input Parameters: 1513 + mat - the matrix 1514 . v - a logically two-dimensional array of values 1515 . m - the number of rows 1516 . idxm - the global indices of the rows 1517 . n - the number of columns 1518 . idxn - the global indices of the columns 1519 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1520 1521 Level: beginner 1522 1523 Notes: 1524 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1525 1526 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1527 options cannot be mixed without intervening calls to the assembly 1528 routines. 1529 1530 `MatSetValues()` uses 0-based row and column numbers in Fortran 1531 as well as in C. 1532 1533 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1534 simply ignored. This allows easily inserting element stiffness matrices 1535 with homogeneous Dirichlet boundary conditions that you don't want represented 1536 in the matrix. 1537 1538 Efficiency Alert: 1539 The routine `MatSetValuesBlocked()` may offer much better efficiency 1540 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1541 1542 Fortran Notes: 1543 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1544 .vb 1545 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1546 .ve 1547 1548 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1549 1550 Developer Note: 1551 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1552 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1553 1554 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1555 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1556 @*/ 1557 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1558 { 1559 PetscFunctionBeginHot; 1560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1561 PetscValidType(mat, 1); 1562 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1563 PetscAssertPointer(idxm, 3); 1564 PetscAssertPointer(idxn, 5); 1565 MatCheckPreallocated(mat, 1); 1566 1567 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1568 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1569 1570 if (PetscDefined(USE_DEBUG)) { 1571 PetscInt i, j; 1572 1573 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1574 if (v) { 1575 for (i = 0; i < m; i++) { 1576 for (j = 0; j < n; j++) { 1577 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1578 #if defined(PETSC_USE_COMPLEX) 1579 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]); 1580 #else 1581 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]); 1582 #endif 1583 } 1584 } 1585 } 1586 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); 1587 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); 1588 } 1589 1590 if (mat->assembled) { 1591 mat->was_assembled = PETSC_TRUE; 1592 mat->assembled = PETSC_FALSE; 1593 } 1594 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1595 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1596 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1597 PetscFunctionReturn(PETSC_SUCCESS); 1598 } 1599 1600 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1601 /*@ 1602 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1603 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1604 MUST be called after all calls to `MatSetValues()` have been completed. 1605 1606 Not Collective 1607 1608 Input Parameters: 1609 + mat - the matrix 1610 . v - a logically two-dimensional array of values 1611 . ism - the rows to provide 1612 . isn - the columns to provide 1613 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1614 1615 Level: beginner 1616 1617 Notes: 1618 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1619 1620 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1621 options cannot be mixed without intervening calls to the assembly 1622 routines. 1623 1624 `MatSetValues()` uses 0-based row and column numbers in Fortran 1625 as well as in C. 1626 1627 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1628 simply ignored. This allows easily inserting element stiffness matrices 1629 with homogeneous Dirichlet boundary conditions that you don't want represented 1630 in the matrix. 1631 1632 Efficiency Alert: 1633 The routine `MatSetValuesBlocked()` may offer much better efficiency 1634 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1635 1636 This is currently not optimized for any particular `ISType` 1637 1638 Developer Note: 1639 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1640 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1641 1642 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1643 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1644 @*/ 1645 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1646 { 1647 PetscInt m, n; 1648 const PetscInt *rows, *cols; 1649 1650 PetscFunctionBeginHot; 1651 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1652 PetscCall(ISGetIndices(ism, &rows)); 1653 PetscCall(ISGetIndices(isn, &cols)); 1654 PetscCall(ISGetLocalSize(ism, &m)); 1655 PetscCall(ISGetLocalSize(isn, &n)); 1656 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1657 PetscCall(ISRestoreIndices(ism, &rows)); 1658 PetscCall(ISRestoreIndices(isn, &cols)); 1659 PetscFunctionReturn(PETSC_SUCCESS); 1660 } 1661 1662 /*@ 1663 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1664 values into a matrix 1665 1666 Not Collective 1667 1668 Input Parameters: 1669 + mat - the matrix 1670 . row - the (block) row to set 1671 - v - a logically two-dimensional array of values 1672 1673 Level: intermediate 1674 1675 Notes: 1676 The values, `v`, are column-oriented (for the block version) and sorted 1677 1678 All the nonzero values in `row` must be provided 1679 1680 The matrix must have previously had its column indices set, likely by having been assembled. 1681 1682 `row` must belong to this MPI process 1683 1684 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1685 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1686 @*/ 1687 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1688 { 1689 PetscInt globalrow; 1690 1691 PetscFunctionBegin; 1692 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1693 PetscValidType(mat, 1); 1694 PetscAssertPointer(v, 3); 1695 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1696 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1697 PetscFunctionReturn(PETSC_SUCCESS); 1698 } 1699 1700 /*@ 1701 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1702 values into a matrix 1703 1704 Not Collective 1705 1706 Input Parameters: 1707 + mat - the matrix 1708 . row - the (block) row to set 1709 - 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 1710 1711 Level: advanced 1712 1713 Notes: 1714 The values, `v`, are column-oriented for the block version. 1715 1716 All the nonzeros in `row` must be provided 1717 1718 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1719 1720 `row` must belong to this process 1721 1722 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1723 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1724 @*/ 1725 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1726 { 1727 PetscFunctionBeginHot; 1728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1729 PetscValidType(mat, 1); 1730 MatCheckPreallocated(mat, 1); 1731 PetscAssertPointer(v, 3); 1732 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1733 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1734 mat->insertmode = INSERT_VALUES; 1735 1736 if (mat->assembled) { 1737 mat->was_assembled = PETSC_TRUE; 1738 mat->assembled = PETSC_FALSE; 1739 } 1740 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1741 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1742 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1743 PetscFunctionReturn(PETSC_SUCCESS); 1744 } 1745 1746 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1747 /*@ 1748 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1749 Using structured grid indexing 1750 1751 Not Collective 1752 1753 Input Parameters: 1754 + mat - the matrix 1755 . m - number of rows being entered 1756 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1757 . n - number of columns being entered 1758 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1759 . v - a logically two-dimensional array of values 1760 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1761 1762 Level: beginner 1763 1764 Notes: 1765 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1766 1767 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1768 options cannot be mixed without intervening calls to the assembly 1769 routines. 1770 1771 The grid coordinates are across the entire grid, not just the local portion 1772 1773 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1774 as well as in C. 1775 1776 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1777 1778 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1779 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1780 1781 The columns and rows in the stencil passed in MUST be contained within the 1782 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1783 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1784 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1785 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1786 1787 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1788 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1789 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1790 `DM_BOUNDARY_PERIODIC` boundary type. 1791 1792 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 1793 a single value per point) you can skip filling those indices. 1794 1795 Inspired by the structured grid interface to the HYPRE package 1796 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1797 1798 Efficiency Alert: 1799 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1800 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1801 1802 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1803 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1804 @*/ 1805 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1806 { 1807 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1808 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1809 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1810 1811 PetscFunctionBegin; 1812 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1814 PetscValidType(mat, 1); 1815 PetscAssertPointer(idxm, 3); 1816 PetscAssertPointer(idxn, 5); 1817 1818 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1819 jdxm = buf; 1820 jdxn = buf + m; 1821 } else { 1822 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1823 jdxm = bufm; 1824 jdxn = bufn; 1825 } 1826 for (i = 0; i < m; i++) { 1827 for (j = 0; j < 3 - sdim; j++) dxm++; 1828 tmp = *dxm++ - starts[0]; 1829 for (j = 0; j < dim - 1; j++) { 1830 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1831 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1832 } 1833 if (mat->stencil.noc) dxm++; 1834 jdxm[i] = tmp; 1835 } 1836 for (i = 0; i < n; i++) { 1837 for (j = 0; j < 3 - sdim; j++) dxn++; 1838 tmp = *dxn++ - starts[0]; 1839 for (j = 0; j < dim - 1; j++) { 1840 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1841 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1842 } 1843 if (mat->stencil.noc) dxn++; 1844 jdxn[i] = tmp; 1845 } 1846 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1847 PetscCall(PetscFree2(bufm, bufn)); 1848 PetscFunctionReturn(PETSC_SUCCESS); 1849 } 1850 1851 /*@ 1852 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1853 Using structured grid indexing 1854 1855 Not Collective 1856 1857 Input Parameters: 1858 + mat - the matrix 1859 . m - number of rows being entered 1860 . idxm - grid coordinates for matrix rows being entered 1861 . n - number of columns being entered 1862 . idxn - grid coordinates for matrix columns being entered 1863 . v - a logically two-dimensional array of values 1864 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1865 1866 Level: beginner 1867 1868 Notes: 1869 By default the values, `v`, are row-oriented and unsorted. 1870 See `MatSetOption()` for other options. 1871 1872 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1873 options cannot be mixed without intervening calls to the assembly 1874 routines. 1875 1876 The grid coordinates are across the entire grid, not just the local portion 1877 1878 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1879 as well as in C. 1880 1881 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1882 1883 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1884 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1885 1886 The columns and rows in the stencil passed in MUST be contained within the 1887 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1888 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1889 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1890 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1891 1892 Negative indices may be passed in idxm and idxn, these rows and columns are 1893 simply ignored. This allows easily inserting element stiffness matrices 1894 with homogeneous Dirichlet boundary conditions that you don't want represented 1895 in the matrix. 1896 1897 Inspired by the structured grid interface to the HYPRE package 1898 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1899 1900 Fortran Note: 1901 `idxm` and `idxn` should be declared as 1902 $ MatStencil idxm(4,m),idxn(4,n) 1903 and the values inserted using 1904 .vb 1905 idxm(MatStencil_i,1) = i 1906 idxm(MatStencil_j,1) = j 1907 idxm(MatStencil_k,1) = k 1908 etc 1909 .ve 1910 1911 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1912 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1913 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1914 @*/ 1915 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1916 { 1917 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1918 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1919 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1920 1921 PetscFunctionBegin; 1922 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1924 PetscValidType(mat, 1); 1925 PetscAssertPointer(idxm, 3); 1926 PetscAssertPointer(idxn, 5); 1927 PetscAssertPointer(v, 6); 1928 1929 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1930 jdxm = buf; 1931 jdxn = buf + m; 1932 } else { 1933 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1934 jdxm = bufm; 1935 jdxn = bufn; 1936 } 1937 for (i = 0; i < m; i++) { 1938 for (j = 0; j < 3 - sdim; j++) dxm++; 1939 tmp = *dxm++ - starts[0]; 1940 for (j = 0; j < sdim - 1; j++) { 1941 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1942 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1943 } 1944 dxm++; 1945 jdxm[i] = tmp; 1946 } 1947 for (i = 0; i < n; i++) { 1948 for (j = 0; j < 3 - sdim; j++) dxn++; 1949 tmp = *dxn++ - starts[0]; 1950 for (j = 0; j < sdim - 1; j++) { 1951 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1952 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1953 } 1954 dxn++; 1955 jdxn[i] = tmp; 1956 } 1957 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1958 PetscCall(PetscFree2(bufm, bufn)); 1959 PetscFunctionReturn(PETSC_SUCCESS); 1960 } 1961 1962 /*@ 1963 MatSetStencil - Sets the grid information for setting values into a matrix via 1964 `MatSetValuesStencil()` 1965 1966 Not Collective 1967 1968 Input Parameters: 1969 + mat - the matrix 1970 . dim - dimension of the grid 1, 2, or 3 1971 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1972 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1973 - dof - number of degrees of freedom per node 1974 1975 Level: beginner 1976 1977 Notes: 1978 Inspired by the structured grid interface to the HYPRE package 1979 (www.llnl.gov/CASC/hyper) 1980 1981 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1982 user. 1983 1984 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1985 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1986 @*/ 1987 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1988 { 1989 PetscFunctionBegin; 1990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1991 PetscAssertPointer(dims, 3); 1992 PetscAssertPointer(starts, 4); 1993 1994 mat->stencil.dim = dim + (dof > 1); 1995 for (PetscInt i = 0; i < dim; i++) { 1996 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1997 mat->stencil.starts[i] = starts[dim - i - 1]; 1998 } 1999 mat->stencil.dims[dim] = dof; 2000 mat->stencil.starts[dim] = 0; 2001 mat->stencil.noc = (PetscBool)(dof == 1); 2002 PetscFunctionReturn(PETSC_SUCCESS); 2003 } 2004 2005 /*@ 2006 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2007 2008 Not Collective 2009 2010 Input Parameters: 2011 + mat - the matrix 2012 . v - a logically two-dimensional array of values 2013 . m - the number of block rows 2014 . idxm - the global block indices 2015 . n - the number of block columns 2016 . idxn - the global block indices 2017 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2018 2019 Level: intermediate 2020 2021 Notes: 2022 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2023 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2024 2025 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2026 NOT the total number of rows/columns; for example, if the block size is 2 and 2027 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2028 The values in `idxm` would be 1 2; that is the first index for each block divided by 2029 the block size. 2030 2031 You must call `MatSetBlockSize()` when constructing this matrix (before 2032 preallocating it). 2033 2034 By default the values, `v`, are row-oriented, so the layout of 2035 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2036 2037 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2038 options cannot be mixed without intervening calls to the assembly 2039 routines. 2040 2041 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2042 as well as in C. 2043 2044 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2045 simply ignored. This allows easily inserting element stiffness matrices 2046 with homogeneous Dirichlet boundary conditions that you don't want represented 2047 in the matrix. 2048 2049 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2050 internal searching must be done to determine where to place the 2051 data in the matrix storage space. By instead inserting blocks of 2052 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2053 reduced. 2054 2055 Example: 2056 .vb 2057 Suppose m=n=2 and block size(bs) = 2 The array is 2058 2059 1 2 | 3 4 2060 5 6 | 7 8 2061 - - - | - - - 2062 9 10 | 11 12 2063 13 14 | 15 16 2064 2065 v[] should be passed in like 2066 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2067 2068 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2069 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2070 .ve 2071 2072 Fortran Notes: 2073 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2074 .vb 2075 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2076 .ve 2077 2078 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2079 2080 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2081 @*/ 2082 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2083 { 2084 PetscFunctionBeginHot; 2085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2086 PetscValidType(mat, 1); 2087 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2088 PetscAssertPointer(idxm, 3); 2089 PetscAssertPointer(idxn, 5); 2090 MatCheckPreallocated(mat, 1); 2091 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2092 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2093 if (PetscDefined(USE_DEBUG)) { 2094 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2095 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2096 } 2097 if (PetscDefined(USE_DEBUG)) { 2098 PetscInt rbs, cbs, M, N, i; 2099 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2100 PetscCall(MatGetSize(mat, &M, &N)); 2101 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); 2102 for (i = 0; i < n; i++) 2103 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); 2104 } 2105 if (mat->assembled) { 2106 mat->was_assembled = PETSC_TRUE; 2107 mat->assembled = PETSC_FALSE; 2108 } 2109 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2110 if (mat->ops->setvaluesblocked) { 2111 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2112 } else { 2113 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2114 PetscInt i, j, bs, cbs; 2115 2116 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2117 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2118 iidxm = buf; 2119 iidxn = buf + m * bs; 2120 } else { 2121 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2122 iidxm = bufr; 2123 iidxn = bufc; 2124 } 2125 for (i = 0; i < m; i++) { 2126 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2127 } 2128 if (m != n || bs != cbs || idxm != idxn) { 2129 for (i = 0; i < n; i++) { 2130 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2131 } 2132 } else iidxn = iidxm; 2133 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2134 PetscCall(PetscFree2(bufr, bufc)); 2135 } 2136 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2137 PetscFunctionReturn(PETSC_SUCCESS); 2138 } 2139 2140 /*@ 2141 MatGetValues - Gets a block of local values from a matrix. 2142 2143 Not Collective; can only return values that are owned by the give process 2144 2145 Input Parameters: 2146 + mat - the matrix 2147 . v - a logically two-dimensional array for storing the values 2148 . m - the number of rows 2149 . idxm - the global indices of the rows 2150 . n - the number of columns 2151 - idxn - the global indices of the columns 2152 2153 Level: advanced 2154 2155 Notes: 2156 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2157 The values, `v`, are then returned in a row-oriented format, 2158 analogous to that used by default in `MatSetValues()`. 2159 2160 `MatGetValues()` uses 0-based row and column numbers in 2161 Fortran as well as in C. 2162 2163 `MatGetValues()` requires that the matrix has been assembled 2164 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2165 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2166 without intermediate matrix assembly. 2167 2168 Negative row or column indices will be ignored and those locations in `v` will be 2169 left unchanged. 2170 2171 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2172 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2173 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2174 2175 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2176 @*/ 2177 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2178 { 2179 PetscFunctionBegin; 2180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2181 PetscValidType(mat, 1); 2182 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2183 PetscAssertPointer(idxm, 3); 2184 PetscAssertPointer(idxn, 5); 2185 PetscAssertPointer(v, 6); 2186 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2187 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2188 MatCheckPreallocated(mat, 1); 2189 2190 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2191 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2192 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2193 PetscFunctionReturn(PETSC_SUCCESS); 2194 } 2195 2196 /*@ 2197 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2198 defined previously by `MatSetLocalToGlobalMapping()` 2199 2200 Not Collective 2201 2202 Input Parameters: 2203 + mat - the matrix 2204 . nrow - number of rows 2205 . irow - the row local indices 2206 . ncol - number of columns 2207 - icol - the column local indices 2208 2209 Output Parameter: 2210 . y - a logically two-dimensional array of values 2211 2212 Level: advanced 2213 2214 Notes: 2215 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2216 2217 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, 2218 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2219 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2220 with `MatSetLocalToGlobalMapping()`. 2221 2222 Developer Note: 2223 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2224 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2225 2226 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2227 `MatSetValuesLocal()`, `MatGetValues()` 2228 @*/ 2229 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2230 { 2231 PetscFunctionBeginHot; 2232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2233 PetscValidType(mat, 1); 2234 MatCheckPreallocated(mat, 1); 2235 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2236 PetscAssertPointer(irow, 3); 2237 PetscAssertPointer(icol, 5); 2238 if (PetscDefined(USE_DEBUG)) { 2239 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2240 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2241 } 2242 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2243 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2244 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2245 else { 2246 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2247 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2248 irowm = buf; 2249 icolm = buf + nrow; 2250 } else { 2251 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2252 irowm = bufr; 2253 icolm = bufc; 2254 } 2255 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2256 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2257 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2258 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2259 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2260 PetscCall(PetscFree2(bufr, bufc)); 2261 } 2262 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2263 PetscFunctionReturn(PETSC_SUCCESS); 2264 } 2265 2266 /*@ 2267 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2268 the same size. Currently, this can only be called once and creates the given matrix. 2269 2270 Not Collective 2271 2272 Input Parameters: 2273 + mat - the matrix 2274 . nb - the number of blocks 2275 . bs - the number of rows (and columns) in each block 2276 . rows - a concatenation of the rows for each block 2277 - v - a concatenation of logically two-dimensional arrays of values 2278 2279 Level: advanced 2280 2281 Notes: 2282 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2283 2284 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2285 2286 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2287 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2288 @*/ 2289 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2290 { 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2293 PetscValidType(mat, 1); 2294 PetscAssertPointer(rows, 4); 2295 PetscAssertPointer(v, 5); 2296 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2297 2298 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2299 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2300 else { 2301 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2302 } 2303 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2304 PetscFunctionReturn(PETSC_SUCCESS); 2305 } 2306 2307 /*@ 2308 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2309 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2310 using a local (per-processor) numbering. 2311 2312 Not Collective 2313 2314 Input Parameters: 2315 + x - the matrix 2316 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2317 - cmapping - column mapping 2318 2319 Level: intermediate 2320 2321 Note: 2322 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2323 2324 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2325 @*/ 2326 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2327 { 2328 PetscFunctionBegin; 2329 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2330 PetscValidType(x, 1); 2331 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2332 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2333 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2334 else { 2335 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2336 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2337 } 2338 PetscFunctionReturn(PETSC_SUCCESS); 2339 } 2340 2341 /*@ 2342 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2343 2344 Not Collective 2345 2346 Input Parameter: 2347 . A - the matrix 2348 2349 Output Parameters: 2350 + rmapping - row mapping 2351 - cmapping - column mapping 2352 2353 Level: advanced 2354 2355 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2356 @*/ 2357 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2358 { 2359 PetscFunctionBegin; 2360 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2361 PetscValidType(A, 1); 2362 if (rmapping) { 2363 PetscAssertPointer(rmapping, 2); 2364 *rmapping = A->rmap->mapping; 2365 } 2366 if (cmapping) { 2367 PetscAssertPointer(cmapping, 3); 2368 *cmapping = A->cmap->mapping; 2369 } 2370 PetscFunctionReturn(PETSC_SUCCESS); 2371 } 2372 2373 /*@ 2374 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2375 2376 Logically Collective 2377 2378 Input Parameters: 2379 + A - the matrix 2380 . rmap - row layout 2381 - cmap - column layout 2382 2383 Level: advanced 2384 2385 Note: 2386 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2387 2388 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2389 @*/ 2390 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2391 { 2392 PetscFunctionBegin; 2393 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2394 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2395 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2396 PetscFunctionReturn(PETSC_SUCCESS); 2397 } 2398 2399 /*@ 2400 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2401 2402 Not Collective 2403 2404 Input Parameter: 2405 . A - the matrix 2406 2407 Output Parameters: 2408 + rmap - row layout 2409 - cmap - column layout 2410 2411 Level: advanced 2412 2413 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2414 @*/ 2415 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2419 PetscValidType(A, 1); 2420 if (rmap) { 2421 PetscAssertPointer(rmap, 2); 2422 *rmap = A->rmap; 2423 } 2424 if (cmap) { 2425 PetscAssertPointer(cmap, 3); 2426 *cmap = A->cmap; 2427 } 2428 PetscFunctionReturn(PETSC_SUCCESS); 2429 } 2430 2431 /*@ 2432 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2433 using a local numbering of the rows and columns. 2434 2435 Not Collective 2436 2437 Input Parameters: 2438 + mat - the matrix 2439 . nrow - number of rows 2440 . irow - the row local indices 2441 . ncol - number of columns 2442 . icol - the column local indices 2443 . y - a logically two-dimensional array of values 2444 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2445 2446 Level: intermediate 2447 2448 Notes: 2449 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2450 2451 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2452 options cannot be mixed without intervening calls to the assembly 2453 routines. 2454 2455 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2456 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2457 2458 Fortran Notes: 2459 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2460 .vb 2461 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2462 .ve 2463 2464 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2465 2466 Developer Note: 2467 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2468 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2469 2470 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2471 `MatGetValuesLocal()` 2472 @*/ 2473 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2474 { 2475 PetscFunctionBeginHot; 2476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2477 PetscValidType(mat, 1); 2478 MatCheckPreallocated(mat, 1); 2479 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2480 PetscAssertPointer(irow, 3); 2481 PetscAssertPointer(icol, 5); 2482 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2483 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2484 if (PetscDefined(USE_DEBUG)) { 2485 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2486 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2487 } 2488 2489 if (mat->assembled) { 2490 mat->was_assembled = PETSC_TRUE; 2491 mat->assembled = PETSC_FALSE; 2492 } 2493 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2494 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2495 else { 2496 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2497 const PetscInt *irowm, *icolm; 2498 2499 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2500 bufr = buf; 2501 bufc = buf + nrow; 2502 irowm = bufr; 2503 icolm = bufc; 2504 } else { 2505 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2506 irowm = bufr; 2507 icolm = bufc; 2508 } 2509 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2510 else irowm = irow; 2511 if (mat->cmap->mapping) { 2512 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2513 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2514 } else icolm = irowm; 2515 } else icolm = icol; 2516 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2517 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2518 } 2519 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2520 PetscFunctionReturn(PETSC_SUCCESS); 2521 } 2522 2523 /*@ 2524 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2525 using a local ordering of the nodes a block at a time. 2526 2527 Not Collective 2528 2529 Input Parameters: 2530 + mat - the matrix 2531 . nrow - number of rows 2532 . irow - the row local indices 2533 . ncol - number of columns 2534 . icol - the column local indices 2535 . y - a logically two-dimensional array of values 2536 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2537 2538 Level: intermediate 2539 2540 Notes: 2541 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2542 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2543 2544 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2545 options cannot be mixed without intervening calls to the assembly 2546 routines. 2547 2548 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2549 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2550 2551 Fortran Notes: 2552 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2553 .vb 2554 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2555 .ve 2556 2557 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2558 2559 Developer Note: 2560 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2561 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2562 2563 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2564 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2565 @*/ 2566 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2567 { 2568 PetscFunctionBeginHot; 2569 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2570 PetscValidType(mat, 1); 2571 MatCheckPreallocated(mat, 1); 2572 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2573 PetscAssertPointer(irow, 3); 2574 PetscAssertPointer(icol, 5); 2575 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2576 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2577 if (PetscDefined(USE_DEBUG)) { 2578 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2579 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); 2580 } 2581 2582 if (mat->assembled) { 2583 mat->was_assembled = PETSC_TRUE; 2584 mat->assembled = PETSC_FALSE; 2585 } 2586 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2587 PetscInt irbs, rbs; 2588 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2589 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2590 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2591 } 2592 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2593 PetscInt icbs, cbs; 2594 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2595 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2596 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2597 } 2598 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2599 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2600 else { 2601 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2602 const PetscInt *irowm, *icolm; 2603 2604 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2605 bufr = buf; 2606 bufc = buf + nrow; 2607 irowm = bufr; 2608 icolm = bufc; 2609 } else { 2610 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2611 irowm = bufr; 2612 icolm = bufc; 2613 } 2614 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2615 else irowm = irow; 2616 if (mat->cmap->mapping) { 2617 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2618 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2619 } else icolm = irowm; 2620 } else icolm = icol; 2621 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2622 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2623 } 2624 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2625 PetscFunctionReturn(PETSC_SUCCESS); 2626 } 2627 2628 /*@ 2629 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2630 2631 Collective 2632 2633 Input Parameters: 2634 + mat - the matrix 2635 - x - the vector to be multiplied 2636 2637 Output Parameter: 2638 . y - the result 2639 2640 Level: developer 2641 2642 Note: 2643 The vectors `x` and `y` cannot be the same. I.e., one cannot 2644 call `MatMultDiagonalBlock`(A,y,y). 2645 2646 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2647 @*/ 2648 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2649 { 2650 PetscFunctionBegin; 2651 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2652 PetscValidType(mat, 1); 2653 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2654 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2655 2656 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2657 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2658 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2659 MatCheckPreallocated(mat, 1); 2660 2661 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2662 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2663 PetscFunctionReturn(PETSC_SUCCESS); 2664 } 2665 2666 /*@ 2667 MatMult - Computes the matrix-vector product, $y = Ax$. 2668 2669 Neighbor-wise Collective 2670 2671 Input Parameters: 2672 + mat - the matrix 2673 - x - the vector to be multiplied 2674 2675 Output Parameter: 2676 . y - the result 2677 2678 Level: beginner 2679 2680 Note: 2681 The vectors `x` and `y` cannot be the same. I.e., one cannot 2682 call `MatMult`(A,y,y). 2683 2684 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2685 @*/ 2686 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2687 { 2688 PetscFunctionBegin; 2689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2690 PetscValidType(mat, 1); 2691 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2692 VecCheckAssembled(x); 2693 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2694 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2695 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2696 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2697 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); 2698 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); 2699 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); 2700 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); 2701 PetscCall(VecSetErrorIfLocked(y, 3)); 2702 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2703 MatCheckPreallocated(mat, 1); 2704 2705 PetscCall(VecLockReadPush(x)); 2706 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2707 PetscUseTypeMethod(mat, mult, x, y); 2708 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2709 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2710 PetscCall(VecLockReadPop(x)); 2711 PetscFunctionReturn(PETSC_SUCCESS); 2712 } 2713 2714 /*@ 2715 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2716 2717 Neighbor-wise Collective 2718 2719 Input Parameters: 2720 + mat - the matrix 2721 - x - the vector to be multiplied 2722 2723 Output Parameter: 2724 . y - the result 2725 2726 Level: beginner 2727 2728 Notes: 2729 The vectors `x` and `y` cannot be the same. I.e., one cannot 2730 call `MatMultTranspose`(A,y,y). 2731 2732 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2733 use `MatMultHermitianTranspose()` 2734 2735 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2736 @*/ 2737 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2738 { 2739 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2740 2741 PetscFunctionBegin; 2742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2743 PetscValidType(mat, 1); 2744 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2745 VecCheckAssembled(x); 2746 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2747 2748 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2749 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2750 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2751 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); 2752 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); 2753 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); 2754 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); 2755 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2756 MatCheckPreallocated(mat, 1); 2757 2758 if (!mat->ops->multtranspose) { 2759 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2760 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); 2761 } else op = mat->ops->multtranspose; 2762 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2763 PetscCall(VecLockReadPush(x)); 2764 PetscCall((*op)(mat, x, y)); 2765 PetscCall(VecLockReadPop(x)); 2766 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2767 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2768 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2769 PetscFunctionReturn(PETSC_SUCCESS); 2770 } 2771 2772 /*@ 2773 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2774 2775 Neighbor-wise Collective 2776 2777 Input Parameters: 2778 + mat - the matrix 2779 - x - the vector to be multiplied 2780 2781 Output Parameter: 2782 . y - the result 2783 2784 Level: beginner 2785 2786 Notes: 2787 The vectors `x` and `y` cannot be the same. I.e., one cannot 2788 call `MatMultHermitianTranspose`(A,y,y). 2789 2790 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2791 2792 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2793 2794 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2795 @*/ 2796 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2797 { 2798 PetscFunctionBegin; 2799 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2800 PetscValidType(mat, 1); 2801 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2802 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2803 2804 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2805 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2806 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2807 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); 2808 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); 2809 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); 2810 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); 2811 MatCheckPreallocated(mat, 1); 2812 2813 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2814 #if defined(PETSC_USE_COMPLEX) 2815 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2816 PetscCall(VecLockReadPush(x)); 2817 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2818 else PetscUseTypeMethod(mat, mult, x, y); 2819 PetscCall(VecLockReadPop(x)); 2820 } else { 2821 Vec w; 2822 PetscCall(VecDuplicate(x, &w)); 2823 PetscCall(VecCopy(x, w)); 2824 PetscCall(VecConjugate(w)); 2825 PetscCall(MatMultTranspose(mat, w, y)); 2826 PetscCall(VecDestroy(&w)); 2827 PetscCall(VecConjugate(y)); 2828 } 2829 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2830 #else 2831 PetscCall(MatMultTranspose(mat, x, y)); 2832 #endif 2833 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2834 PetscFunctionReturn(PETSC_SUCCESS); 2835 } 2836 2837 /*@ 2838 MatMultAdd - Computes $v3 = v2 + A * v1$. 2839 2840 Neighbor-wise Collective 2841 2842 Input Parameters: 2843 + mat - the matrix 2844 . v1 - the vector to be multiplied by `mat` 2845 - v2 - the vector to be added to the result 2846 2847 Output Parameter: 2848 . v3 - the result 2849 2850 Level: beginner 2851 2852 Note: 2853 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2854 call `MatMultAdd`(A,v1,v2,v1). 2855 2856 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2857 @*/ 2858 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2859 { 2860 PetscFunctionBegin; 2861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2862 PetscValidType(mat, 1); 2863 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2864 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2865 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2866 2867 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2868 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2869 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); 2870 /* 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); 2871 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); */ 2872 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); 2873 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); 2874 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2875 MatCheckPreallocated(mat, 1); 2876 2877 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2878 PetscCall(VecLockReadPush(v1)); 2879 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2880 PetscCall(VecLockReadPop(v1)); 2881 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2882 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2883 PetscFunctionReturn(PETSC_SUCCESS); 2884 } 2885 2886 /*@ 2887 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2888 2889 Neighbor-wise Collective 2890 2891 Input Parameters: 2892 + mat - the matrix 2893 . v1 - the vector to be multiplied by the transpose of the matrix 2894 - v2 - the vector to be added to the result 2895 2896 Output Parameter: 2897 . v3 - the result 2898 2899 Level: beginner 2900 2901 Note: 2902 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2903 call `MatMultTransposeAdd`(A,v1,v2,v1). 2904 2905 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2906 @*/ 2907 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2908 { 2909 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2910 2911 PetscFunctionBegin; 2912 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2913 PetscValidType(mat, 1); 2914 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2915 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2916 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2917 2918 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2919 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2920 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); 2921 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); 2922 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); 2923 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2924 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2925 MatCheckPreallocated(mat, 1); 2926 2927 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2928 PetscCall(VecLockReadPush(v1)); 2929 PetscCall((*op)(mat, v1, v2, v3)); 2930 PetscCall(VecLockReadPop(v1)); 2931 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2932 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2933 PetscFunctionReturn(PETSC_SUCCESS); 2934 } 2935 2936 /*@ 2937 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2938 2939 Neighbor-wise Collective 2940 2941 Input Parameters: 2942 + mat - the matrix 2943 . v1 - the vector to be multiplied by the Hermitian transpose 2944 - v2 - the vector to be added to the result 2945 2946 Output Parameter: 2947 . v3 - the result 2948 2949 Level: beginner 2950 2951 Note: 2952 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2953 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2954 2955 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2956 @*/ 2957 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2958 { 2959 PetscFunctionBegin; 2960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2961 PetscValidType(mat, 1); 2962 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2963 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2964 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2965 2966 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2967 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2968 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2969 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); 2970 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); 2971 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); 2972 MatCheckPreallocated(mat, 1); 2973 2974 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2975 PetscCall(VecLockReadPush(v1)); 2976 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2977 else { 2978 Vec w, z; 2979 PetscCall(VecDuplicate(v1, &w)); 2980 PetscCall(VecCopy(v1, w)); 2981 PetscCall(VecConjugate(w)); 2982 PetscCall(VecDuplicate(v3, &z)); 2983 PetscCall(MatMultTranspose(mat, w, z)); 2984 PetscCall(VecDestroy(&w)); 2985 PetscCall(VecConjugate(z)); 2986 if (v2 != v3) { 2987 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2988 } else { 2989 PetscCall(VecAXPY(v3, 1.0, z)); 2990 } 2991 PetscCall(VecDestroy(&z)); 2992 } 2993 PetscCall(VecLockReadPop(v1)); 2994 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2995 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2996 PetscFunctionReturn(PETSC_SUCCESS); 2997 } 2998 2999 /*@ 3000 MatGetFactorType - gets the type of factorization a matrix is 3001 3002 Not Collective 3003 3004 Input Parameter: 3005 . mat - the matrix 3006 3007 Output Parameter: 3008 . 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` 3009 3010 Level: intermediate 3011 3012 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3013 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3014 @*/ 3015 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3016 { 3017 PetscFunctionBegin; 3018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3019 PetscValidType(mat, 1); 3020 PetscAssertPointer(t, 2); 3021 *t = mat->factortype; 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 /*@ 3026 MatSetFactorType - sets the type of factorization a matrix is 3027 3028 Logically Collective 3029 3030 Input Parameters: 3031 + mat - the matrix 3032 - 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` 3033 3034 Level: intermediate 3035 3036 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3037 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3038 @*/ 3039 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3040 { 3041 PetscFunctionBegin; 3042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3043 PetscValidType(mat, 1); 3044 mat->factortype = t; 3045 PetscFunctionReturn(PETSC_SUCCESS); 3046 } 3047 3048 /*@ 3049 MatGetInfo - Returns information about matrix storage (number of 3050 nonzeros, memory, etc.). 3051 3052 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3053 3054 Input Parameters: 3055 + mat - the matrix 3056 - 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) 3057 3058 Output Parameter: 3059 . info - matrix information context 3060 3061 Options Database Key: 3062 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3063 3064 Level: intermediate 3065 3066 Notes: 3067 The `MatInfo` context contains a variety of matrix data, including 3068 number of nonzeros allocated and used, number of mallocs during 3069 matrix assembly, etc. Additional information for factored matrices 3070 is provided (such as the fill ratio, number of mallocs during 3071 factorization, etc.). 3072 3073 Example: 3074 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3075 data within the `MatInfo` context. For example, 3076 .vb 3077 MatInfo info; 3078 Mat A; 3079 double mal, nz_a, nz_u; 3080 3081 MatGetInfo(A, MAT_LOCAL, &info); 3082 mal = info.mallocs; 3083 nz_a = info.nz_allocated; 3084 .ve 3085 3086 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3087 @*/ 3088 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3089 { 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3092 PetscValidType(mat, 1); 3093 PetscAssertPointer(info, 3); 3094 MatCheckPreallocated(mat, 1); 3095 PetscUseTypeMethod(mat, getinfo, flag, info); 3096 PetscFunctionReturn(PETSC_SUCCESS); 3097 } 3098 3099 /* 3100 This is used by external packages where it is not easy to get the info from the actual 3101 matrix factorization. 3102 */ 3103 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3104 { 3105 PetscFunctionBegin; 3106 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3107 PetscFunctionReturn(PETSC_SUCCESS); 3108 } 3109 3110 /*@ 3111 MatLUFactor - Performs in-place LU factorization of matrix. 3112 3113 Collective 3114 3115 Input Parameters: 3116 + mat - the matrix 3117 . row - row permutation 3118 . col - column permutation 3119 - info - options for factorization, includes 3120 .vb 3121 fill - expected fill as ratio of original fill. 3122 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3123 Run with the option -info to determine an optimal value to use 3124 .ve 3125 3126 Level: developer 3127 3128 Notes: 3129 Most users should employ the `KSP` interface for linear solvers 3130 instead of working directly with matrix algebra routines such as this. 3131 See, e.g., `KSPCreate()`. 3132 3133 This changes the state of the matrix to a factored matrix; it cannot be used 3134 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3135 3136 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3137 when not using `KSP`. 3138 3139 Developer Note: 3140 The Fortran interface is not autogenerated as the 3141 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3142 3143 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3144 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3145 @*/ 3146 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3147 { 3148 MatFactorInfo tinfo; 3149 3150 PetscFunctionBegin; 3151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3152 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3153 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3154 if (info) PetscAssertPointer(info, 4); 3155 PetscValidType(mat, 1); 3156 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3157 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3158 MatCheckPreallocated(mat, 1); 3159 if (!info) { 3160 PetscCall(MatFactorInfoInitialize(&tinfo)); 3161 info = &tinfo; 3162 } 3163 3164 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3165 PetscUseTypeMethod(mat, lufactor, row, col, info); 3166 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3167 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3168 PetscFunctionReturn(PETSC_SUCCESS); 3169 } 3170 3171 /*@ 3172 MatILUFactor - Performs in-place ILU factorization of matrix. 3173 3174 Collective 3175 3176 Input Parameters: 3177 + mat - the matrix 3178 . row - row permutation 3179 . col - column permutation 3180 - info - structure containing 3181 .vb 3182 levels - number of levels of fill. 3183 expected fill - as ratio of original fill. 3184 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3185 missing diagonal entries) 3186 .ve 3187 3188 Level: developer 3189 3190 Notes: 3191 Most users should employ the `KSP` interface for linear solvers 3192 instead of working directly with matrix algebra routines such as this. 3193 See, e.g., `KSPCreate()`. 3194 3195 Probably really in-place only when level of fill is zero, otherwise allocates 3196 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3197 when not using `KSP`. 3198 3199 Developer Note: 3200 The Fortran interface is not autogenerated as the 3201 interface definition cannot be generated correctly [due to MatFactorInfo] 3202 3203 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3204 @*/ 3205 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3206 { 3207 PetscFunctionBegin; 3208 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3209 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3210 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3211 PetscAssertPointer(info, 4); 3212 PetscValidType(mat, 1); 3213 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3214 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3215 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3216 MatCheckPreallocated(mat, 1); 3217 3218 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3219 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3220 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3221 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3222 PetscFunctionReturn(PETSC_SUCCESS); 3223 } 3224 3225 /*@ 3226 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3227 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3228 3229 Collective 3230 3231 Input Parameters: 3232 + fact - the factor matrix obtained with `MatGetFactor()` 3233 . mat - the matrix 3234 . row - the row permutation 3235 . col - the column permutation 3236 - info - options for factorization, includes 3237 .vb 3238 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3239 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3240 .ve 3241 3242 Level: developer 3243 3244 Notes: 3245 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3246 3247 Most users should employ the simplified `KSP` interface for linear solvers 3248 instead of working directly with matrix algebra routines such as this. 3249 See, e.g., `KSPCreate()`. 3250 3251 Developer Note: 3252 The Fortran interface is not autogenerated as the 3253 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3254 3255 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3256 @*/ 3257 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3258 { 3259 MatFactorInfo tinfo; 3260 3261 PetscFunctionBegin; 3262 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3263 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3264 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3265 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3266 if (info) PetscAssertPointer(info, 5); 3267 PetscValidType(fact, 1); 3268 PetscValidType(mat, 2); 3269 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3270 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3271 MatCheckPreallocated(mat, 2); 3272 if (!info) { 3273 PetscCall(MatFactorInfoInitialize(&tinfo)); 3274 info = &tinfo; 3275 } 3276 3277 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3278 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3279 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3280 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3281 PetscFunctionReturn(PETSC_SUCCESS); 3282 } 3283 3284 /*@ 3285 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3286 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3287 3288 Collective 3289 3290 Input Parameters: 3291 + fact - the factor matrix obtained with `MatGetFactor()` 3292 . mat - the matrix 3293 - info - options for factorization 3294 3295 Level: developer 3296 3297 Notes: 3298 See `MatLUFactor()` for in-place factorization. See 3299 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3300 3301 Most users should employ the `KSP` interface for linear solvers 3302 instead of working directly with matrix algebra routines such as this. 3303 See, e.g., `KSPCreate()`. 3304 3305 Developer Note: 3306 The Fortran interface is not autogenerated as the 3307 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3308 3309 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3310 @*/ 3311 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3312 { 3313 MatFactorInfo tinfo; 3314 3315 PetscFunctionBegin; 3316 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3318 PetscValidType(fact, 1); 3319 PetscValidType(mat, 2); 3320 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3321 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, 3322 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3323 3324 MatCheckPreallocated(mat, 2); 3325 if (!info) { 3326 PetscCall(MatFactorInfoInitialize(&tinfo)); 3327 info = &tinfo; 3328 } 3329 3330 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3331 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3332 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3333 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3334 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3335 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3336 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3337 PetscFunctionReturn(PETSC_SUCCESS); 3338 } 3339 3340 /*@ 3341 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3342 symmetric matrix. 3343 3344 Collective 3345 3346 Input Parameters: 3347 + mat - the matrix 3348 . perm - row and column permutations 3349 - info - expected fill as ratio of original fill 3350 3351 Level: developer 3352 3353 Notes: 3354 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3355 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3356 3357 Most users should employ the `KSP` interface for linear solvers 3358 instead of working directly with matrix algebra routines such as this. 3359 See, e.g., `KSPCreate()`. 3360 3361 Developer Note: 3362 The Fortran interface is not autogenerated as the 3363 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3364 3365 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3366 `MatGetOrdering()` 3367 @*/ 3368 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3369 { 3370 MatFactorInfo tinfo; 3371 3372 PetscFunctionBegin; 3373 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3374 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3375 if (info) PetscAssertPointer(info, 3); 3376 PetscValidType(mat, 1); 3377 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3378 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3379 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3380 MatCheckPreallocated(mat, 1); 3381 if (!info) { 3382 PetscCall(MatFactorInfoInitialize(&tinfo)); 3383 info = &tinfo; 3384 } 3385 3386 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3387 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3388 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3389 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3390 PetscFunctionReturn(PETSC_SUCCESS); 3391 } 3392 3393 /*@ 3394 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3395 of a symmetric matrix. 3396 3397 Collective 3398 3399 Input Parameters: 3400 + fact - the factor matrix obtained with `MatGetFactor()` 3401 . mat - the matrix 3402 . perm - row and column permutations 3403 - info - options for factorization, includes 3404 .vb 3405 fill - expected fill as ratio of original fill. 3406 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3407 Run with the option -info to determine an optimal value to use 3408 .ve 3409 3410 Level: developer 3411 3412 Notes: 3413 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3414 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3415 3416 Most users should employ the `KSP` interface for linear solvers 3417 instead of working directly with matrix algebra routines such as this. 3418 See, e.g., `KSPCreate()`. 3419 3420 Developer Note: 3421 The Fortran interface is not autogenerated as the 3422 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3423 3424 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3425 `MatGetOrdering()` 3426 @*/ 3427 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3428 { 3429 MatFactorInfo tinfo; 3430 3431 PetscFunctionBegin; 3432 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3434 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3435 if (info) PetscAssertPointer(info, 4); 3436 PetscValidType(fact, 1); 3437 PetscValidType(mat, 2); 3438 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3439 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3440 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3441 MatCheckPreallocated(mat, 2); 3442 if (!info) { 3443 PetscCall(MatFactorInfoInitialize(&tinfo)); 3444 info = &tinfo; 3445 } 3446 3447 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3448 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3449 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3450 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3451 PetscFunctionReturn(PETSC_SUCCESS); 3452 } 3453 3454 /*@ 3455 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3456 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3457 `MatCholeskyFactorSymbolic()`. 3458 3459 Collective 3460 3461 Input Parameters: 3462 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3463 . mat - the initial matrix that is to be factored 3464 - info - options for factorization 3465 3466 Level: developer 3467 3468 Note: 3469 Most users should employ the `KSP` interface for linear solvers 3470 instead of working directly with matrix algebra routines such as this. 3471 See, e.g., `KSPCreate()`. 3472 3473 Developer Note: 3474 The Fortran interface is not autogenerated as the 3475 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3476 3477 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3478 @*/ 3479 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3480 { 3481 MatFactorInfo tinfo; 3482 3483 PetscFunctionBegin; 3484 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3486 PetscValidType(fact, 1); 3487 PetscValidType(mat, 2); 3488 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3489 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, 3490 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3491 MatCheckPreallocated(mat, 2); 3492 if (!info) { 3493 PetscCall(MatFactorInfoInitialize(&tinfo)); 3494 info = &tinfo; 3495 } 3496 3497 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3498 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3499 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3500 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3501 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3502 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3503 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3504 PetscFunctionReturn(PETSC_SUCCESS); 3505 } 3506 3507 /*@ 3508 MatQRFactor - Performs in-place QR factorization of matrix. 3509 3510 Collective 3511 3512 Input Parameters: 3513 + mat - the matrix 3514 . col - column permutation 3515 - info - options for factorization, includes 3516 .vb 3517 fill - expected fill as ratio of original fill. 3518 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3519 Run with the option -info to determine an optimal value to use 3520 .ve 3521 3522 Level: developer 3523 3524 Notes: 3525 Most users should employ the `KSP` interface for linear solvers 3526 instead of working directly with matrix algebra routines such as this. 3527 See, e.g., `KSPCreate()`. 3528 3529 This changes the state of the matrix to a factored matrix; it cannot be used 3530 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3531 3532 Developer Note: 3533 The Fortran interface is not autogenerated as the 3534 interface definition cannot be generated correctly [due to MatFactorInfo] 3535 3536 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3537 `MatSetUnfactored()` 3538 @*/ 3539 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3540 { 3541 PetscFunctionBegin; 3542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3543 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3544 if (info) PetscAssertPointer(info, 3); 3545 PetscValidType(mat, 1); 3546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3547 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3548 MatCheckPreallocated(mat, 1); 3549 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3550 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3551 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3552 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3553 PetscFunctionReturn(PETSC_SUCCESS); 3554 } 3555 3556 /*@ 3557 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3558 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3559 3560 Collective 3561 3562 Input Parameters: 3563 + fact - the factor matrix obtained with `MatGetFactor()` 3564 . mat - the matrix 3565 . col - column permutation 3566 - info - options for factorization, includes 3567 .vb 3568 fill - expected fill as ratio of original fill. 3569 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3570 Run with the option -info to determine an optimal value to use 3571 .ve 3572 3573 Level: developer 3574 3575 Note: 3576 Most users should employ the `KSP` interface for linear solvers 3577 instead of working directly with matrix algebra routines such as this. 3578 See, e.g., `KSPCreate()`. 3579 3580 Developer Note: 3581 The Fortran interface is not autogenerated as the 3582 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3583 3584 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3585 @*/ 3586 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3587 { 3588 MatFactorInfo tinfo; 3589 3590 PetscFunctionBegin; 3591 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3593 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3594 if (info) PetscAssertPointer(info, 4); 3595 PetscValidType(fact, 1); 3596 PetscValidType(mat, 2); 3597 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3598 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3599 MatCheckPreallocated(mat, 2); 3600 if (!info) { 3601 PetscCall(MatFactorInfoInitialize(&tinfo)); 3602 info = &tinfo; 3603 } 3604 3605 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3606 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3607 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3608 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3609 PetscFunctionReturn(PETSC_SUCCESS); 3610 } 3611 3612 /*@ 3613 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3614 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3615 3616 Collective 3617 3618 Input Parameters: 3619 + fact - the factor matrix obtained with `MatGetFactor()` 3620 . mat - the matrix 3621 - info - options for factorization 3622 3623 Level: developer 3624 3625 Notes: 3626 See `MatQRFactor()` for in-place factorization. 3627 3628 Most users should employ the `KSP` interface for linear solvers 3629 instead of working directly with matrix algebra routines such as this. 3630 See, e.g., `KSPCreate()`. 3631 3632 Developer Note: 3633 The Fortran interface is not autogenerated as the 3634 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3635 3636 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3637 @*/ 3638 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3639 { 3640 MatFactorInfo tinfo; 3641 3642 PetscFunctionBegin; 3643 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3645 PetscValidType(fact, 1); 3646 PetscValidType(mat, 2); 3647 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3648 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, 3649 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3650 3651 MatCheckPreallocated(mat, 2); 3652 if (!info) { 3653 PetscCall(MatFactorInfoInitialize(&tinfo)); 3654 info = &tinfo; 3655 } 3656 3657 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3658 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3659 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3660 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3661 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3662 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3663 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3664 PetscFunctionReturn(PETSC_SUCCESS); 3665 } 3666 3667 /*@ 3668 MatSolve - Solves $A x = b$, given a factored matrix. 3669 3670 Neighbor-wise Collective 3671 3672 Input Parameters: 3673 + mat - the factored matrix 3674 - b - the right-hand-side vector 3675 3676 Output Parameter: 3677 . x - the result vector 3678 3679 Level: developer 3680 3681 Notes: 3682 The vectors `b` and `x` cannot be the same. I.e., one cannot 3683 call `MatSolve`(A,x,x). 3684 3685 Most users should employ the `KSP` interface for linear solvers 3686 instead of working directly with matrix algebra routines such as this. 3687 See, e.g., `KSPCreate()`. 3688 3689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3690 @*/ 3691 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3692 { 3693 PetscFunctionBegin; 3694 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3695 PetscValidType(mat, 1); 3696 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3697 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3698 PetscCheckSameComm(mat, 1, b, 2); 3699 PetscCheckSameComm(mat, 1, x, 3); 3700 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3701 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); 3702 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); 3703 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); 3704 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3705 MatCheckPreallocated(mat, 1); 3706 3707 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3708 PetscCall(VecFlag(x, mat->factorerrortype)); 3709 if (mat->factorerrortype) { 3710 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3711 } else PetscUseTypeMethod(mat, solve, b, x); 3712 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3713 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3714 PetscFunctionReturn(PETSC_SUCCESS); 3715 } 3716 3717 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3718 { 3719 Vec b, x; 3720 PetscInt N, i; 3721 PetscErrorCode (*f)(Mat, Vec, Vec); 3722 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3723 3724 PetscFunctionBegin; 3725 if (A->factorerrortype) { 3726 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3727 PetscCall(MatSetInf(X)); 3728 PetscFunctionReturn(PETSC_SUCCESS); 3729 } 3730 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3731 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3732 PetscCall(MatBoundToCPU(A, &Abound)); 3733 if (!Abound) { 3734 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3735 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3736 } 3737 #if PetscDefined(HAVE_CUDA) 3738 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3739 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3740 #elif PetscDefined(HAVE_HIP) 3741 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3742 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3743 #endif 3744 PetscCall(MatGetSize(B, NULL, &N)); 3745 for (i = 0; i < N; i++) { 3746 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3747 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3748 PetscCall((*f)(A, b, x)); 3749 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3750 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3751 } 3752 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3753 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3754 PetscFunctionReturn(PETSC_SUCCESS); 3755 } 3756 3757 /*@ 3758 MatMatSolve - Solves $A X = B$, given a factored matrix. 3759 3760 Neighbor-wise Collective 3761 3762 Input Parameters: 3763 + A - the factored matrix 3764 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3765 3766 Output Parameter: 3767 . X - the result matrix (dense matrix) 3768 3769 Level: developer 3770 3771 Note: 3772 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3773 otherwise, `B` and `X` cannot be the same. 3774 3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3776 @*/ 3777 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3778 { 3779 PetscFunctionBegin; 3780 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3781 PetscValidType(A, 1); 3782 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3783 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3784 PetscCheckSameComm(A, 1, B, 2); 3785 PetscCheckSameComm(A, 1, X, 3); 3786 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); 3787 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); 3788 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"); 3789 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3790 MatCheckPreallocated(A, 1); 3791 3792 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3793 if (!A->ops->matsolve) { 3794 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3795 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3796 } else PetscUseTypeMethod(A, matsolve, B, X); 3797 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3798 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3799 PetscFunctionReturn(PETSC_SUCCESS); 3800 } 3801 3802 /*@ 3803 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3804 3805 Neighbor-wise Collective 3806 3807 Input Parameters: 3808 + A - the factored matrix 3809 - B - the right-hand-side matrix (`MATDENSE` matrix) 3810 3811 Output Parameter: 3812 . X - the result matrix (dense matrix) 3813 3814 Level: developer 3815 3816 Note: 3817 The matrices `B` and `X` cannot be the same. I.e., one cannot 3818 call `MatMatSolveTranspose`(A,X,X). 3819 3820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3821 @*/ 3822 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3823 { 3824 PetscFunctionBegin; 3825 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3826 PetscValidType(A, 1); 3827 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3828 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3829 PetscCheckSameComm(A, 1, B, 2); 3830 PetscCheckSameComm(A, 1, X, 3); 3831 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3832 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); 3833 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); 3834 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); 3835 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"); 3836 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3837 MatCheckPreallocated(A, 1); 3838 3839 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3840 if (!A->ops->matsolvetranspose) { 3841 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3842 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3843 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3844 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3845 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3846 PetscFunctionReturn(PETSC_SUCCESS); 3847 } 3848 3849 /*@ 3850 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3851 3852 Neighbor-wise Collective 3853 3854 Input Parameters: 3855 + A - the factored matrix 3856 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3857 3858 Output Parameter: 3859 . X - the result matrix (dense matrix) 3860 3861 Level: developer 3862 3863 Note: 3864 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 3865 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3866 3867 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3868 @*/ 3869 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3870 { 3871 PetscFunctionBegin; 3872 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3873 PetscValidType(A, 1); 3874 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3875 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3876 PetscCheckSameComm(A, 1, Bt, 2); 3877 PetscCheckSameComm(A, 1, X, 3); 3878 3879 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3880 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); 3881 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); 3882 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"); 3883 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3884 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3885 MatCheckPreallocated(A, 1); 3886 3887 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3888 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3889 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3890 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3891 PetscFunctionReturn(PETSC_SUCCESS); 3892 } 3893 3894 /*@ 3895 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3896 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3897 3898 Neighbor-wise Collective 3899 3900 Input Parameters: 3901 + mat - the factored matrix 3902 - b - the right-hand-side vector 3903 3904 Output Parameter: 3905 . x - the result vector 3906 3907 Level: developer 3908 3909 Notes: 3910 `MatSolve()` should be used for most applications, as it performs 3911 a forward solve followed by a backward solve. 3912 3913 The vectors `b` and `x` cannot be the same, i.e., one cannot 3914 call `MatForwardSolve`(A,x,x). 3915 3916 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3917 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3918 `MatForwardSolve()` solves $U^T*D y = b$, and 3919 `MatBackwardSolve()` solves $U x = y$. 3920 Thus they do not provide a symmetric preconditioner. 3921 3922 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3923 @*/ 3924 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3925 { 3926 PetscFunctionBegin; 3927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3928 PetscValidType(mat, 1); 3929 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3930 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3931 PetscCheckSameComm(mat, 1, b, 2); 3932 PetscCheckSameComm(mat, 1, x, 3); 3933 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3934 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); 3935 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); 3936 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); 3937 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3938 MatCheckPreallocated(mat, 1); 3939 3940 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3941 PetscUseTypeMethod(mat, forwardsolve, b, x); 3942 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3943 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3944 PetscFunctionReturn(PETSC_SUCCESS); 3945 } 3946 3947 /*@ 3948 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3949 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3950 3951 Neighbor-wise Collective 3952 3953 Input Parameters: 3954 + mat - the factored matrix 3955 - b - the right-hand-side vector 3956 3957 Output Parameter: 3958 . x - the result vector 3959 3960 Level: developer 3961 3962 Notes: 3963 `MatSolve()` should be used for most applications, as it performs 3964 a forward solve followed by a backward solve. 3965 3966 The vectors `b` and `x` cannot be the same. I.e., one cannot 3967 call `MatBackwardSolve`(A,x,x). 3968 3969 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3970 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3971 `MatForwardSolve()` solves $U^T*D y = b$, and 3972 `MatBackwardSolve()` solves $U x = y$. 3973 Thus they do not provide a symmetric preconditioner. 3974 3975 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3976 @*/ 3977 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3978 { 3979 PetscFunctionBegin; 3980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3981 PetscValidType(mat, 1); 3982 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3983 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3984 PetscCheckSameComm(mat, 1, b, 2); 3985 PetscCheckSameComm(mat, 1, x, 3); 3986 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3987 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); 3988 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); 3989 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); 3990 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3991 MatCheckPreallocated(mat, 1); 3992 3993 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3994 PetscUseTypeMethod(mat, backwardsolve, b, x); 3995 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3996 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3997 PetscFunctionReturn(PETSC_SUCCESS); 3998 } 3999 4000 /*@ 4001 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4002 4003 Neighbor-wise Collective 4004 4005 Input Parameters: 4006 + mat - the factored matrix 4007 . b - the right-hand-side vector 4008 - y - the vector to be added to 4009 4010 Output Parameter: 4011 . x - the result vector 4012 4013 Level: developer 4014 4015 Note: 4016 The vectors `b` and `x` cannot be the same. I.e., one cannot 4017 call `MatSolveAdd`(A,x,y,x). 4018 4019 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4020 @*/ 4021 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4022 { 4023 PetscScalar one = 1.0; 4024 Vec tmp; 4025 4026 PetscFunctionBegin; 4027 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4028 PetscValidType(mat, 1); 4029 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4030 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4031 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4032 PetscCheckSameComm(mat, 1, b, 2); 4033 PetscCheckSameComm(mat, 1, y, 3); 4034 PetscCheckSameComm(mat, 1, x, 4); 4035 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4036 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); 4037 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); 4038 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); 4039 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); 4040 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); 4041 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4042 MatCheckPreallocated(mat, 1); 4043 4044 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4045 PetscCall(VecFlag(x, mat->factorerrortype)); 4046 if (mat->factorerrortype) { 4047 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4048 } else if (mat->ops->solveadd) { 4049 PetscUseTypeMethod(mat, solveadd, b, y, x); 4050 } else { 4051 /* do the solve then the add manually */ 4052 if (x != y) { 4053 PetscCall(MatSolve(mat, b, x)); 4054 PetscCall(VecAXPY(x, one, y)); 4055 } else { 4056 PetscCall(VecDuplicate(x, &tmp)); 4057 PetscCall(VecCopy(x, tmp)); 4058 PetscCall(MatSolve(mat, b, x)); 4059 PetscCall(VecAXPY(x, one, tmp)); 4060 PetscCall(VecDestroy(&tmp)); 4061 } 4062 } 4063 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4064 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4065 PetscFunctionReturn(PETSC_SUCCESS); 4066 } 4067 4068 /*@ 4069 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4070 4071 Neighbor-wise Collective 4072 4073 Input Parameters: 4074 + mat - the factored matrix 4075 - b - the right-hand-side vector 4076 4077 Output Parameter: 4078 . x - the result vector 4079 4080 Level: developer 4081 4082 Notes: 4083 The vectors `b` and `x` cannot be the same. I.e., one cannot 4084 call `MatSolveTranspose`(A,x,x). 4085 4086 Most users should employ the `KSP` interface for linear solvers 4087 instead of working directly with matrix algebra routines such as this. 4088 See, e.g., `KSPCreate()`. 4089 4090 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4091 @*/ 4092 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4093 { 4094 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4095 4096 PetscFunctionBegin; 4097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4098 PetscValidType(mat, 1); 4099 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4100 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4101 PetscCheckSameComm(mat, 1, b, 2); 4102 PetscCheckSameComm(mat, 1, x, 3); 4103 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4104 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); 4105 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); 4106 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4107 MatCheckPreallocated(mat, 1); 4108 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4109 PetscCall(VecFlag(x, mat->factorerrortype)); 4110 if (mat->factorerrortype) { 4111 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4112 } else { 4113 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4114 PetscCall((*f)(mat, b, x)); 4115 } 4116 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4117 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4118 PetscFunctionReturn(PETSC_SUCCESS); 4119 } 4120 4121 /*@ 4122 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4123 factored matrix. 4124 4125 Neighbor-wise Collective 4126 4127 Input Parameters: 4128 + mat - the factored matrix 4129 . b - the right-hand-side vector 4130 - y - the vector to be added to 4131 4132 Output Parameter: 4133 . x - the result vector 4134 4135 Level: developer 4136 4137 Note: 4138 The vectors `b` and `x` cannot be the same. I.e., one cannot 4139 call `MatSolveTransposeAdd`(A,x,y,x). 4140 4141 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4142 @*/ 4143 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4144 { 4145 PetscScalar one = 1.0; 4146 Vec tmp; 4147 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4148 4149 PetscFunctionBegin; 4150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4151 PetscValidType(mat, 1); 4152 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4153 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4154 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4155 PetscCheckSameComm(mat, 1, b, 2); 4156 PetscCheckSameComm(mat, 1, y, 3); 4157 PetscCheckSameComm(mat, 1, x, 4); 4158 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4159 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); 4160 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); 4161 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); 4162 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); 4163 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4164 MatCheckPreallocated(mat, 1); 4165 4166 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4167 PetscCall(VecFlag(x, mat->factorerrortype)); 4168 if (mat->factorerrortype) { 4169 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4170 } else if (f) { 4171 PetscCall((*f)(mat, b, y, x)); 4172 } else { 4173 /* do the solve then the add manually */ 4174 if (x != y) { 4175 PetscCall(MatSolveTranspose(mat, b, x)); 4176 PetscCall(VecAXPY(x, one, y)); 4177 } else { 4178 PetscCall(VecDuplicate(x, &tmp)); 4179 PetscCall(VecCopy(x, tmp)); 4180 PetscCall(MatSolveTranspose(mat, b, x)); 4181 PetscCall(VecAXPY(x, one, tmp)); 4182 PetscCall(VecDestroy(&tmp)); 4183 } 4184 } 4185 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4186 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4187 PetscFunctionReturn(PETSC_SUCCESS); 4188 } 4189 4190 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4191 /*@ 4192 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4193 4194 Neighbor-wise Collective 4195 4196 Input Parameters: 4197 + mat - the matrix 4198 . b - the right-hand side 4199 . omega - the relaxation factor 4200 . flag - flag indicating the type of SOR (see below) 4201 . shift - diagonal shift 4202 . its - the number of iterations 4203 - lits - the number of local iterations 4204 4205 Output Parameter: 4206 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4207 4208 SOR Flags: 4209 + `SOR_FORWARD_SWEEP` - forward SOR 4210 . `SOR_BACKWARD_SWEEP` - backward SOR 4211 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4212 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4213 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4214 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4215 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4216 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4217 upper/lower triangular part of matrix to 4218 vector (with omega) 4219 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4220 4221 Level: developer 4222 4223 Notes: 4224 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4225 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4226 on each processor. 4227 4228 Application programmers will not generally use `MatSOR()` directly, 4229 but instead will employ the `KSP`/`PC` interface. 4230 4231 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4232 4233 Most users should employ the `KSP` interface for linear solvers 4234 instead of working directly with matrix algebra routines such as this. 4235 See, e.g., `KSPCreate()`. 4236 4237 Vectors `x` and `b` CANNOT be the same 4238 4239 The flags are implemented as bitwise inclusive or operations. 4240 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4241 to specify a zero initial guess for SSOR. 4242 4243 Developer Note: 4244 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4245 4246 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4247 @*/ 4248 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4249 { 4250 PetscFunctionBegin; 4251 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4252 PetscValidType(mat, 1); 4253 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4254 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4255 PetscCheckSameComm(mat, 1, b, 2); 4256 PetscCheckSameComm(mat, 1, x, 8); 4257 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4258 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4259 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); 4260 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); 4261 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); 4262 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4263 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4264 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4265 4266 MatCheckPreallocated(mat, 1); 4267 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4268 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4269 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4270 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4271 PetscFunctionReturn(PETSC_SUCCESS); 4272 } 4273 4274 /* 4275 Default matrix copy routine. 4276 */ 4277 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4278 { 4279 PetscInt i, rstart = 0, rend = 0, nz; 4280 const PetscInt *cwork; 4281 const PetscScalar *vwork; 4282 4283 PetscFunctionBegin; 4284 if (B->assembled) PetscCall(MatZeroEntries(B)); 4285 if (str == SAME_NONZERO_PATTERN) { 4286 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4287 for (i = rstart; i < rend; i++) { 4288 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4289 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4290 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4291 } 4292 } else { 4293 PetscCall(MatAYPX(B, 0.0, A, str)); 4294 } 4295 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4296 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4297 PetscFunctionReturn(PETSC_SUCCESS); 4298 } 4299 4300 /*@ 4301 MatCopy - Copies a matrix to another matrix. 4302 4303 Collective 4304 4305 Input Parameters: 4306 + A - the matrix 4307 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4308 4309 Output Parameter: 4310 . B - where the copy is put 4311 4312 Level: intermediate 4313 4314 Notes: 4315 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4316 4317 `MatCopy()` copies the matrix entries of a matrix to another existing 4318 matrix (after first zeroing the second matrix). A related routine is 4319 `MatConvert()`, which first creates a new matrix and then copies the data. 4320 4321 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4322 @*/ 4323 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4324 { 4325 PetscInt i; 4326 4327 PetscFunctionBegin; 4328 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4329 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4330 PetscValidType(A, 1); 4331 PetscValidType(B, 2); 4332 PetscCheckSameComm(A, 1, B, 2); 4333 MatCheckPreallocated(B, 2); 4334 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4335 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4336 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, 4337 A->cmap->N, B->cmap->N); 4338 MatCheckPreallocated(A, 1); 4339 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4340 4341 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4342 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4343 else PetscCall(MatCopy_Basic(A, B, str)); 4344 4345 B->stencil.dim = A->stencil.dim; 4346 B->stencil.noc = A->stencil.noc; 4347 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4348 B->stencil.dims[i] = A->stencil.dims[i]; 4349 B->stencil.starts[i] = A->stencil.starts[i]; 4350 } 4351 4352 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4353 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4354 PetscFunctionReturn(PETSC_SUCCESS); 4355 } 4356 4357 /*@ 4358 MatConvert - Converts a matrix to another matrix, either of the same 4359 or different type. 4360 4361 Collective 4362 4363 Input Parameters: 4364 + mat - the matrix 4365 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4366 same type as the original matrix. 4367 - reuse - denotes if the destination matrix is to be created or reused. 4368 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 4369 `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). 4370 4371 Output Parameter: 4372 . M - pointer to place new matrix 4373 4374 Level: intermediate 4375 4376 Notes: 4377 `MatConvert()` first creates a new matrix and then copies the data from 4378 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4379 entries of one matrix to another already existing matrix context. 4380 4381 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4382 the MPI communicator of the generated matrix is always the same as the communicator 4383 of the input matrix. 4384 4385 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4386 @*/ 4387 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4388 { 4389 PetscBool sametype, issame, flg; 4390 PetscBool3 issymmetric, ishermitian; 4391 char convname[256], mtype[256]; 4392 Mat B; 4393 4394 PetscFunctionBegin; 4395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4396 PetscValidType(mat, 1); 4397 PetscAssertPointer(M, 4); 4398 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4399 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4400 MatCheckPreallocated(mat, 1); 4401 4402 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4403 if (flg) newtype = mtype; 4404 4405 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4406 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4407 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4408 if (reuse == MAT_REUSE_MATRIX) { 4409 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4410 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4411 } 4412 4413 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4414 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4415 PetscFunctionReturn(PETSC_SUCCESS); 4416 } 4417 4418 /* Cache Mat options because some converters use MatHeaderReplace */ 4419 issymmetric = mat->symmetric; 4420 ishermitian = mat->hermitian; 4421 4422 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4423 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4424 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4425 } else { 4426 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4427 const char *prefix[3] = {"seq", "mpi", ""}; 4428 PetscInt i; 4429 /* 4430 Order of precedence: 4431 0) See if newtype is a superclass of the current matrix. 4432 1) See if a specialized converter is known to the current matrix. 4433 2) See if a specialized converter is known to the desired matrix class. 4434 3) See if a good general converter is registered for the desired class 4435 (as of 6/27/03 only MATMPIADJ falls into this category). 4436 4) See if a good general converter is known for the current matrix. 4437 5) Use a really basic converter. 4438 */ 4439 4440 /* 0) See if newtype is a superclass of the current matrix. 4441 i.e mat is mpiaij and newtype is aij */ 4442 for (i = 0; i < 2; i++) { 4443 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4444 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4445 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4446 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4447 if (flg) { 4448 if (reuse == MAT_INPLACE_MATRIX) { 4449 PetscCall(PetscInfo(mat, "Early return\n")); 4450 PetscFunctionReturn(PETSC_SUCCESS); 4451 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4452 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4453 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4454 PetscFunctionReturn(PETSC_SUCCESS); 4455 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4456 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4457 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4458 PetscFunctionReturn(PETSC_SUCCESS); 4459 } 4460 } 4461 } 4462 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4463 for (i = 0; i < 3; i++) { 4464 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4465 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4466 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4467 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4468 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4469 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4470 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4471 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4472 if (conv) goto foundconv; 4473 } 4474 4475 /* 2) See if a specialized converter is known to the desired matrix class. */ 4476 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4477 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4478 PetscCall(MatSetType(B, newtype)); 4479 for (i = 0; i < 3; i++) { 4480 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4481 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4482 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4483 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4484 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4485 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4486 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4487 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4488 if (conv) { 4489 PetscCall(MatDestroy(&B)); 4490 goto foundconv; 4491 } 4492 } 4493 4494 /* 3) See if a good general converter is registered for the desired class */ 4495 conv = B->ops->convertfrom; 4496 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4497 PetscCall(MatDestroy(&B)); 4498 if (conv) goto foundconv; 4499 4500 /* 4) See if a good general converter is known for the current matrix */ 4501 if (mat->ops->convert) conv = mat->ops->convert; 4502 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4503 if (conv) goto foundconv; 4504 4505 /* 5) Use a really basic converter. */ 4506 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4507 conv = MatConvert_Basic; 4508 4509 foundconv: 4510 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4511 PetscCall((*conv)(mat, newtype, reuse, M)); 4512 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4513 /* the block sizes must be same if the mappings are copied over */ 4514 (*M)->rmap->bs = mat->rmap->bs; 4515 (*M)->cmap->bs = mat->cmap->bs; 4516 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4517 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4518 (*M)->rmap->mapping = mat->rmap->mapping; 4519 (*M)->cmap->mapping = mat->cmap->mapping; 4520 } 4521 (*M)->stencil.dim = mat->stencil.dim; 4522 (*M)->stencil.noc = mat->stencil.noc; 4523 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4524 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4525 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4526 } 4527 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4528 } 4529 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4530 4531 /* Copy Mat options */ 4532 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4533 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4534 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4535 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4536 PetscFunctionReturn(PETSC_SUCCESS); 4537 } 4538 4539 /*@ 4540 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4541 4542 Not Collective 4543 4544 Input Parameter: 4545 . mat - the matrix, must be a factored matrix 4546 4547 Output Parameter: 4548 . type - the string name of the package (do not free this string) 4549 4550 Level: intermediate 4551 4552 Fortran Note: 4553 Pass in an empty string that is long enough and the package name will be copied into it. 4554 4555 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4556 @*/ 4557 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4558 { 4559 PetscErrorCode (*conv)(Mat, MatSolverType *); 4560 4561 PetscFunctionBegin; 4562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4563 PetscValidType(mat, 1); 4564 PetscAssertPointer(type, 2); 4565 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4566 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4567 if (conv) PetscCall((*conv)(mat, type)); 4568 else *type = MATSOLVERPETSC; 4569 PetscFunctionReturn(PETSC_SUCCESS); 4570 } 4571 4572 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4573 struct _MatSolverTypeForSpecifcType { 4574 MatType mtype; 4575 /* no entry for MAT_FACTOR_NONE */ 4576 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4577 MatSolverTypeForSpecifcType next; 4578 }; 4579 4580 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4581 struct _MatSolverTypeHolder { 4582 char *name; 4583 MatSolverTypeForSpecifcType handlers; 4584 MatSolverTypeHolder next; 4585 }; 4586 4587 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4588 4589 /*@C 4590 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4591 4592 Logically Collective, No Fortran Support 4593 4594 Input Parameters: 4595 + package - name of the package, for example petsc or superlu 4596 . mtype - the matrix type that works with this package 4597 . ftype - the type of factorization supported by the package 4598 - createfactor - routine that will create the factored matrix ready to be used 4599 4600 Level: developer 4601 4602 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4603 `MatGetFactor()` 4604 @*/ 4605 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4606 { 4607 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4608 PetscBool flg; 4609 MatSolverTypeForSpecifcType inext, iprev = NULL; 4610 4611 PetscFunctionBegin; 4612 PetscCall(MatInitializePackage()); 4613 if (!next) { 4614 PetscCall(PetscNew(&MatSolverTypeHolders)); 4615 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4616 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4617 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4618 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4619 PetscFunctionReturn(PETSC_SUCCESS); 4620 } 4621 while (next) { 4622 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4623 if (flg) { 4624 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4625 inext = next->handlers; 4626 while (inext) { 4627 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4628 if (flg) { 4629 inext->createfactor[(int)ftype - 1] = createfactor; 4630 PetscFunctionReturn(PETSC_SUCCESS); 4631 } 4632 iprev = inext; 4633 inext = inext->next; 4634 } 4635 PetscCall(PetscNew(&iprev->next)); 4636 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4637 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4638 PetscFunctionReturn(PETSC_SUCCESS); 4639 } 4640 prev = next; 4641 next = next->next; 4642 } 4643 PetscCall(PetscNew(&prev->next)); 4644 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4645 PetscCall(PetscNew(&prev->next->handlers)); 4646 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4647 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4648 PetscFunctionReturn(PETSC_SUCCESS); 4649 } 4650 4651 /*@C 4652 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4653 4654 Input Parameters: 4655 + 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 4656 . ftype - the type of factorization supported by the type 4657 - mtype - the matrix type that works with this type 4658 4659 Output Parameters: 4660 + foundtype - `PETSC_TRUE` if the type was registered 4661 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4662 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4663 4664 Calling sequence of `createfactor`: 4665 + A - the matrix providing the factor matrix 4666 . ftype - the `MatFactorType` of the factor requested 4667 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4668 4669 Level: developer 4670 4671 Note: 4672 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4673 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4674 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4675 4676 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4677 `MatInitializePackage()` 4678 @*/ 4679 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4680 { 4681 MatSolverTypeHolder next = MatSolverTypeHolders; 4682 PetscBool flg; 4683 MatSolverTypeForSpecifcType inext; 4684 4685 PetscFunctionBegin; 4686 if (foundtype) *foundtype = PETSC_FALSE; 4687 if (foundmtype) *foundmtype = PETSC_FALSE; 4688 if (createfactor) *createfactor = NULL; 4689 4690 if (type) { 4691 while (next) { 4692 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4693 if (flg) { 4694 if (foundtype) *foundtype = PETSC_TRUE; 4695 inext = next->handlers; 4696 while (inext) { 4697 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4698 if (flg) { 4699 if (foundmtype) *foundmtype = PETSC_TRUE; 4700 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4701 PetscFunctionReturn(PETSC_SUCCESS); 4702 } 4703 inext = inext->next; 4704 } 4705 } 4706 next = next->next; 4707 } 4708 } else { 4709 while (next) { 4710 inext = next->handlers; 4711 while (inext) { 4712 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4713 if (flg && inext->createfactor[(int)ftype - 1]) { 4714 if (foundtype) *foundtype = PETSC_TRUE; 4715 if (foundmtype) *foundmtype = PETSC_TRUE; 4716 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4717 PetscFunctionReturn(PETSC_SUCCESS); 4718 } 4719 inext = inext->next; 4720 } 4721 next = next->next; 4722 } 4723 /* try with base classes inext->mtype */ 4724 next = MatSolverTypeHolders; 4725 while (next) { 4726 inext = next->handlers; 4727 while (inext) { 4728 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4729 if (flg && inext->createfactor[(int)ftype - 1]) { 4730 if (foundtype) *foundtype = PETSC_TRUE; 4731 if (foundmtype) *foundmtype = PETSC_TRUE; 4732 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4733 PetscFunctionReturn(PETSC_SUCCESS); 4734 } 4735 inext = inext->next; 4736 } 4737 next = next->next; 4738 } 4739 } 4740 PetscFunctionReturn(PETSC_SUCCESS); 4741 } 4742 4743 PetscErrorCode MatSolverTypeDestroy(void) 4744 { 4745 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4746 MatSolverTypeForSpecifcType inext, iprev; 4747 4748 PetscFunctionBegin; 4749 while (next) { 4750 PetscCall(PetscFree(next->name)); 4751 inext = next->handlers; 4752 while (inext) { 4753 PetscCall(PetscFree(inext->mtype)); 4754 iprev = inext; 4755 inext = inext->next; 4756 PetscCall(PetscFree(iprev)); 4757 } 4758 prev = next; 4759 next = next->next; 4760 PetscCall(PetscFree(prev)); 4761 } 4762 MatSolverTypeHolders = NULL; 4763 PetscFunctionReturn(PETSC_SUCCESS); 4764 } 4765 4766 /*@ 4767 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4768 4769 Logically Collective 4770 4771 Input Parameter: 4772 . mat - the matrix 4773 4774 Output Parameter: 4775 . flg - `PETSC_TRUE` if uses the ordering 4776 4777 Level: developer 4778 4779 Note: 4780 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4781 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4782 4783 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4784 @*/ 4785 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4786 { 4787 PetscFunctionBegin; 4788 *flg = mat->canuseordering; 4789 PetscFunctionReturn(PETSC_SUCCESS); 4790 } 4791 4792 /*@ 4793 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4794 4795 Logically Collective 4796 4797 Input Parameters: 4798 + mat - the matrix obtained with `MatGetFactor()` 4799 - ftype - the factorization type to be used 4800 4801 Output Parameter: 4802 . otype - the preferred ordering type 4803 4804 Level: developer 4805 4806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4807 @*/ 4808 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4809 { 4810 PetscFunctionBegin; 4811 *otype = mat->preferredordering[ftype]; 4812 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4813 PetscFunctionReturn(PETSC_SUCCESS); 4814 } 4815 4816 /*@ 4817 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4818 4819 Collective 4820 4821 Input Parameters: 4822 + mat - the matrix 4823 . 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 4824 the other criteria is returned 4825 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4826 4827 Output Parameter: 4828 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4829 4830 Options Database Keys: 4831 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4832 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4833 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4834 4835 Level: intermediate 4836 4837 Notes: 4838 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4839 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4840 4841 Users usually access the factorization solvers via `KSP` 4842 4843 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4844 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 4845 4846 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4847 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4848 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4849 4850 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4851 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4852 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4853 4854 Developer Note: 4855 This should actually be called `MatCreateFactor()` since it creates a new factor object 4856 4857 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4858 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4859 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4860 @*/ 4861 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4862 { 4863 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4864 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4865 4866 PetscFunctionBegin; 4867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4868 PetscValidType(mat, 1); 4869 4870 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4871 MatCheckPreallocated(mat, 1); 4872 4873 PetscCall(MatIsShell(mat, &shell)); 4874 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4875 if (hasop) { 4876 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4877 PetscFunctionReturn(PETSC_SUCCESS); 4878 } 4879 4880 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4881 if (!foundtype) { 4882 if (type) { 4883 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], 4884 ((PetscObject)mat)->type_name, type); 4885 } else { 4886 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); 4887 } 4888 } 4889 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4890 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); 4891 4892 PetscCall((*conv)(mat, ftype, f)); 4893 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4894 PetscFunctionReturn(PETSC_SUCCESS); 4895 } 4896 4897 /*@ 4898 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4899 4900 Not Collective 4901 4902 Input Parameters: 4903 + mat - the matrix 4904 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4905 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4906 4907 Output Parameter: 4908 . flg - PETSC_TRUE if the factorization is available 4909 4910 Level: intermediate 4911 4912 Notes: 4913 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4914 such as pastix, superlu, mumps etc. 4915 4916 PETSc must have been ./configure to use the external solver, using the option --download-package 4917 4918 Developer Note: 4919 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4920 4921 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4922 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4923 @*/ 4924 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4925 { 4926 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4927 4928 PetscFunctionBegin; 4929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4930 PetscAssertPointer(flg, 4); 4931 4932 *flg = PETSC_FALSE; 4933 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4934 4935 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4936 MatCheckPreallocated(mat, 1); 4937 4938 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4939 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4940 PetscFunctionReturn(PETSC_SUCCESS); 4941 } 4942 4943 /*@ 4944 MatDuplicate - Duplicates a matrix including the non-zero structure. 4945 4946 Collective 4947 4948 Input Parameters: 4949 + mat - the matrix 4950 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4951 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4952 4953 Output Parameter: 4954 . M - pointer to place new matrix 4955 4956 Level: intermediate 4957 4958 Notes: 4959 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4960 4961 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4962 4963 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. 4964 4965 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4966 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4967 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4968 4969 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4970 @*/ 4971 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4972 { 4973 Mat B; 4974 VecType vtype; 4975 PetscInt i; 4976 PetscObject dm, container_h, container_d; 4977 void (*viewf)(void); 4978 4979 PetscFunctionBegin; 4980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4981 PetscValidType(mat, 1); 4982 PetscAssertPointer(M, 3); 4983 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4984 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4985 MatCheckPreallocated(mat, 1); 4986 4987 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4988 PetscUseTypeMethod(mat, duplicate, op, M); 4989 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4990 B = *M; 4991 4992 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4993 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4994 PetscCall(MatGetVecType(mat, &vtype)); 4995 PetscCall(MatSetVecType(B, vtype)); 4996 4997 B->stencil.dim = mat->stencil.dim; 4998 B->stencil.noc = mat->stencil.noc; 4999 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 5000 B->stencil.dims[i] = mat->stencil.dims[i]; 5001 B->stencil.starts[i] = mat->stencil.starts[i]; 5002 } 5003 5004 B->nooffproczerorows = mat->nooffproczerorows; 5005 B->nooffprocentries = mat->nooffprocentries; 5006 5007 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5008 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5009 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5010 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5011 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5012 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5013 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5014 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5015 PetscFunctionReturn(PETSC_SUCCESS); 5016 } 5017 5018 /*@ 5019 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5020 5021 Logically Collective 5022 5023 Input Parameter: 5024 . mat - the matrix 5025 5026 Output Parameter: 5027 . v - the diagonal of the matrix 5028 5029 Level: intermediate 5030 5031 Note: 5032 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5033 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5034 is larger than `ndiag`, the values of the remaining entries are unspecified. 5035 5036 Currently only correct in parallel for square matrices. 5037 5038 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5039 @*/ 5040 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5041 { 5042 PetscFunctionBegin; 5043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5044 PetscValidType(mat, 1); 5045 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5046 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5047 MatCheckPreallocated(mat, 1); 5048 if (PetscDefined(USE_DEBUG)) { 5049 PetscInt nv, row, col, ndiag; 5050 5051 PetscCall(VecGetLocalSize(v, &nv)); 5052 PetscCall(MatGetLocalSize(mat, &row, &col)); 5053 ndiag = PetscMin(row, col); 5054 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); 5055 } 5056 5057 PetscUseTypeMethod(mat, getdiagonal, v); 5058 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5059 PetscFunctionReturn(PETSC_SUCCESS); 5060 } 5061 5062 /*@ 5063 MatGetRowMin - Gets the minimum value (of the real part) of each 5064 row of the matrix 5065 5066 Logically Collective 5067 5068 Input Parameter: 5069 . mat - the matrix 5070 5071 Output Parameters: 5072 + v - the vector for storing the maximums 5073 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5074 5075 Level: intermediate 5076 5077 Note: 5078 The result of this call are the same as if one converted the matrix to dense format 5079 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5080 5081 This code is only implemented for a couple of matrix formats. 5082 5083 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5084 `MatGetRowMax()` 5085 @*/ 5086 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5087 { 5088 PetscFunctionBegin; 5089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5090 PetscValidType(mat, 1); 5091 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5092 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5093 5094 if (!mat->cmap->N) { 5095 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5096 if (idx) { 5097 PetscInt i, m = mat->rmap->n; 5098 for (i = 0; i < m; i++) idx[i] = -1; 5099 } 5100 } else { 5101 MatCheckPreallocated(mat, 1); 5102 } 5103 PetscUseTypeMethod(mat, getrowmin, v, idx); 5104 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5105 PetscFunctionReturn(PETSC_SUCCESS); 5106 } 5107 5108 /*@ 5109 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5110 row of the matrix 5111 5112 Logically Collective 5113 5114 Input Parameter: 5115 . mat - the matrix 5116 5117 Output Parameters: 5118 + v - the vector for storing the minimums 5119 - idx - the indices of the column found for each row (or `NULL` if not needed) 5120 5121 Level: intermediate 5122 5123 Notes: 5124 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5125 row is 0 (the first column). 5126 5127 This code is only implemented for a couple of matrix formats. 5128 5129 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5130 @*/ 5131 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5132 { 5133 PetscFunctionBegin; 5134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5135 PetscValidType(mat, 1); 5136 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5137 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5138 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5139 5140 if (!mat->cmap->N) { 5141 PetscCall(VecSet(v, 0.0)); 5142 if (idx) { 5143 PetscInt i, m = mat->rmap->n; 5144 for (i = 0; i < m; i++) idx[i] = -1; 5145 } 5146 } else { 5147 MatCheckPreallocated(mat, 1); 5148 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5149 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5150 } 5151 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5152 PetscFunctionReturn(PETSC_SUCCESS); 5153 } 5154 5155 /*@ 5156 MatGetRowMax - Gets the maximum value (of the real part) of each 5157 row of the matrix 5158 5159 Logically Collective 5160 5161 Input Parameter: 5162 . mat - the matrix 5163 5164 Output Parameters: 5165 + v - the vector for storing the maximums 5166 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5167 5168 Level: intermediate 5169 5170 Notes: 5171 The result of this call are the same as if one converted the matrix to dense format 5172 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5173 5174 This code is only implemented for a couple of matrix formats. 5175 5176 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5177 @*/ 5178 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5179 { 5180 PetscFunctionBegin; 5181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5182 PetscValidType(mat, 1); 5183 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5184 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5185 5186 if (!mat->cmap->N) { 5187 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5188 if (idx) { 5189 PetscInt i, m = mat->rmap->n; 5190 for (i = 0; i < m; i++) idx[i] = -1; 5191 } 5192 } else { 5193 MatCheckPreallocated(mat, 1); 5194 PetscUseTypeMethod(mat, getrowmax, v, idx); 5195 } 5196 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5197 PetscFunctionReturn(PETSC_SUCCESS); 5198 } 5199 5200 /*@ 5201 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5202 row of the matrix 5203 5204 Logically Collective 5205 5206 Input Parameter: 5207 . mat - the matrix 5208 5209 Output Parameters: 5210 + v - the vector for storing the maximums 5211 - idx - the indices of the column found for each row (or `NULL` if not needed) 5212 5213 Level: intermediate 5214 5215 Notes: 5216 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5217 row is 0 (the first column). 5218 5219 This code is only implemented for a couple of matrix formats. 5220 5221 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5222 @*/ 5223 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5224 { 5225 PetscFunctionBegin; 5226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5227 PetscValidType(mat, 1); 5228 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5229 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5230 5231 if (!mat->cmap->N) { 5232 PetscCall(VecSet(v, 0.0)); 5233 if (idx) { 5234 PetscInt i, m = mat->rmap->n; 5235 for (i = 0; i < m; i++) idx[i] = -1; 5236 } 5237 } else { 5238 MatCheckPreallocated(mat, 1); 5239 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5240 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5241 } 5242 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5243 PetscFunctionReturn(PETSC_SUCCESS); 5244 } 5245 5246 /*@ 5247 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5248 5249 Logically Collective 5250 5251 Input Parameter: 5252 . mat - the matrix 5253 5254 Output Parameter: 5255 . v - the vector for storing the sum 5256 5257 Level: intermediate 5258 5259 This code is only implemented for a couple of matrix formats. 5260 5261 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5262 @*/ 5263 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5264 { 5265 PetscFunctionBegin; 5266 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5267 PetscValidType(mat, 1); 5268 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5269 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5270 5271 if (!mat->cmap->N) { 5272 PetscCall(VecSet(v, 0.0)); 5273 } else { 5274 MatCheckPreallocated(mat, 1); 5275 PetscUseTypeMethod(mat, getrowsumabs, v); 5276 } 5277 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5278 PetscFunctionReturn(PETSC_SUCCESS); 5279 } 5280 5281 /*@ 5282 MatGetRowSum - Gets the sum of each row of the matrix 5283 5284 Logically or Neighborhood Collective 5285 5286 Input Parameter: 5287 . mat - the matrix 5288 5289 Output Parameter: 5290 . v - the vector for storing the sum of rows 5291 5292 Level: intermediate 5293 5294 Note: 5295 This code is slow since it is not currently specialized for different formats 5296 5297 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5298 @*/ 5299 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5300 { 5301 Vec ones; 5302 5303 PetscFunctionBegin; 5304 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5305 PetscValidType(mat, 1); 5306 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5307 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5308 MatCheckPreallocated(mat, 1); 5309 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5310 PetscCall(VecSet(ones, 1.)); 5311 PetscCall(MatMult(mat, ones, v)); 5312 PetscCall(VecDestroy(&ones)); 5313 PetscFunctionReturn(PETSC_SUCCESS); 5314 } 5315 5316 /*@ 5317 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5318 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5319 5320 Collective 5321 5322 Input Parameter: 5323 . mat - the matrix to provide the transpose 5324 5325 Output Parameter: 5326 . 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 5327 5328 Level: advanced 5329 5330 Note: 5331 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 5332 routine allows bypassing that call. 5333 5334 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5335 @*/ 5336 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5337 { 5338 MatParentState *rb = NULL; 5339 5340 PetscFunctionBegin; 5341 PetscCall(PetscNew(&rb)); 5342 rb->id = ((PetscObject)mat)->id; 5343 rb->state = 0; 5344 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5345 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5346 PetscFunctionReturn(PETSC_SUCCESS); 5347 } 5348 5349 /*@ 5350 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5351 5352 Collective 5353 5354 Input Parameters: 5355 + mat - the matrix to transpose 5356 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5357 5358 Output Parameter: 5359 . B - the transpose of the matrix 5360 5361 Level: intermediate 5362 5363 Notes: 5364 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5365 5366 `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 5367 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5368 5369 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. 5370 5371 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5372 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5373 5374 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5375 5376 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5377 5378 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5379 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5380 @*/ 5381 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5382 { 5383 PetscContainer rB = NULL; 5384 MatParentState *rb = NULL; 5385 5386 PetscFunctionBegin; 5387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5388 PetscValidType(mat, 1); 5389 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5390 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5391 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5392 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5393 MatCheckPreallocated(mat, 1); 5394 if (reuse == MAT_REUSE_MATRIX) { 5395 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5396 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5397 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5398 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5399 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5400 } 5401 5402 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5403 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5404 PetscUseTypeMethod(mat, transpose, reuse, B); 5405 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5406 } 5407 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5408 5409 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5410 if (reuse != MAT_INPLACE_MATRIX) { 5411 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5412 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5413 rb->state = ((PetscObject)mat)->state; 5414 rb->nonzerostate = mat->nonzerostate; 5415 } 5416 PetscFunctionReturn(PETSC_SUCCESS); 5417 } 5418 5419 /*@ 5420 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5421 5422 Collective 5423 5424 Input Parameter: 5425 . A - the matrix to transpose 5426 5427 Output Parameter: 5428 . 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 5429 numerical portion. 5430 5431 Level: intermediate 5432 5433 Note: 5434 This is not supported for many matrix types, use `MatTranspose()` in those cases 5435 5436 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5437 @*/ 5438 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5439 { 5440 PetscFunctionBegin; 5441 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5442 PetscValidType(A, 1); 5443 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5444 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5445 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5446 PetscUseTypeMethod(A, transposesymbolic, B); 5447 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5448 5449 PetscCall(MatTransposeSetPrecursor(A, *B)); 5450 PetscFunctionReturn(PETSC_SUCCESS); 5451 } 5452 5453 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5454 { 5455 PetscContainer rB; 5456 MatParentState *rb; 5457 5458 PetscFunctionBegin; 5459 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5460 PetscValidType(A, 1); 5461 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5462 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5463 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5464 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5465 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5466 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5467 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5468 PetscFunctionReturn(PETSC_SUCCESS); 5469 } 5470 5471 /*@ 5472 MatIsTranspose - Test whether a matrix is another one's transpose, 5473 or its own, in which case it tests symmetry. 5474 5475 Collective 5476 5477 Input Parameters: 5478 + A - the matrix to test 5479 . B - the matrix to test against, this can equal the first parameter 5480 - tol - tolerance, differences between entries smaller than this are counted as zero 5481 5482 Output Parameter: 5483 . flg - the result 5484 5485 Level: intermediate 5486 5487 Notes: 5488 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5489 test involves parallel copies of the block off-diagonal parts of the matrix. 5490 5491 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5492 @*/ 5493 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5494 { 5495 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5496 5497 PetscFunctionBegin; 5498 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5499 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5500 PetscAssertPointer(flg, 4); 5501 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5502 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5503 *flg = PETSC_FALSE; 5504 if (f && g) { 5505 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5506 PetscCall((*f)(A, B, tol, flg)); 5507 } else { 5508 MatType mattype; 5509 5510 PetscCall(MatGetType(f ? B : A, &mattype)); 5511 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5512 } 5513 PetscFunctionReturn(PETSC_SUCCESS); 5514 } 5515 5516 /*@ 5517 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5518 5519 Collective 5520 5521 Input Parameters: 5522 + mat - the matrix to transpose and complex conjugate 5523 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5524 5525 Output Parameter: 5526 . B - the Hermitian transpose 5527 5528 Level: intermediate 5529 5530 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5531 @*/ 5532 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5533 { 5534 PetscFunctionBegin; 5535 PetscCall(MatTranspose(mat, reuse, B)); 5536 #if defined(PETSC_USE_COMPLEX) 5537 PetscCall(MatConjugate(*B)); 5538 #endif 5539 PetscFunctionReturn(PETSC_SUCCESS); 5540 } 5541 5542 /*@ 5543 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5544 5545 Collective 5546 5547 Input Parameters: 5548 + A - the matrix to test 5549 . B - the matrix to test against, this can equal the first parameter 5550 - tol - tolerance, differences between entries smaller than this are counted as zero 5551 5552 Output Parameter: 5553 . flg - the result 5554 5555 Level: intermediate 5556 5557 Notes: 5558 Only available for `MATAIJ` matrices. 5559 5560 The sequential algorithm 5561 has a running time of the order of the number of nonzeros; the parallel 5562 test involves parallel copies of the block off-diagonal parts of the matrix. 5563 5564 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5565 @*/ 5566 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5567 { 5568 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5569 5570 PetscFunctionBegin; 5571 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5572 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5573 PetscAssertPointer(flg, 4); 5574 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5575 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5576 if (f && g) { 5577 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5578 PetscCall((*f)(A, B, tol, flg)); 5579 } 5580 PetscFunctionReturn(PETSC_SUCCESS); 5581 } 5582 5583 /*@ 5584 MatPermute - Creates a new matrix with rows and columns permuted from the 5585 original. 5586 5587 Collective 5588 5589 Input Parameters: 5590 + mat - the matrix to permute 5591 . row - row permutation, each processor supplies only the permutation for its rows 5592 - col - column permutation, each processor supplies only the permutation for its columns 5593 5594 Output Parameter: 5595 . B - the permuted matrix 5596 5597 Level: advanced 5598 5599 Note: 5600 The index sets map from row/col of permuted matrix to row/col of original matrix. 5601 The index sets should be on the same communicator as mat and have the same local sizes. 5602 5603 Developer Note: 5604 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5605 exploit the fact that row and col are permutations, consider implementing the 5606 more general `MatCreateSubMatrix()` instead. 5607 5608 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5609 @*/ 5610 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5611 { 5612 PetscFunctionBegin; 5613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5614 PetscValidType(mat, 1); 5615 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5616 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5617 PetscAssertPointer(B, 4); 5618 PetscCheckSameComm(mat, 1, row, 2); 5619 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5620 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5621 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5622 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5623 MatCheckPreallocated(mat, 1); 5624 5625 if (mat->ops->permute) { 5626 PetscUseTypeMethod(mat, permute, row, col, B); 5627 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5628 } else { 5629 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5630 } 5631 PetscFunctionReturn(PETSC_SUCCESS); 5632 } 5633 5634 /*@ 5635 MatEqual - Compares two matrices. 5636 5637 Collective 5638 5639 Input Parameters: 5640 + A - the first matrix 5641 - B - the second matrix 5642 5643 Output Parameter: 5644 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5645 5646 Level: intermediate 5647 5648 Note: 5649 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 5650 using several randomly created vectors, see `MatMultEqual()`. 5651 5652 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5653 @*/ 5654 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5655 { 5656 PetscFunctionBegin; 5657 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5658 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5659 PetscValidType(A, 1); 5660 PetscValidType(B, 2); 5661 PetscAssertPointer(flg, 3); 5662 PetscCheckSameComm(A, 1, B, 2); 5663 MatCheckPreallocated(A, 1); 5664 MatCheckPreallocated(B, 2); 5665 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5666 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5667 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, 5668 B->cmap->N); 5669 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5670 PetscUseTypeMethod(A, equal, B, flg); 5671 } else { 5672 PetscCall(MatMultEqual(A, B, 10, flg)); 5673 } 5674 PetscFunctionReturn(PETSC_SUCCESS); 5675 } 5676 5677 /*@ 5678 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5679 matrices that are stored as vectors. Either of the two scaling 5680 matrices can be `NULL`. 5681 5682 Collective 5683 5684 Input Parameters: 5685 + mat - the matrix to be scaled 5686 . l - the left scaling vector (or `NULL`) 5687 - r - the right scaling vector (or `NULL`) 5688 5689 Level: intermediate 5690 5691 Note: 5692 `MatDiagonalScale()` computes $A = LAR$, where 5693 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5694 The L scales the rows of the matrix, the R scales the columns of the matrix. 5695 5696 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5697 @*/ 5698 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5699 { 5700 PetscFunctionBegin; 5701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5702 PetscValidType(mat, 1); 5703 if (l) { 5704 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5705 PetscCheckSameComm(mat, 1, l, 2); 5706 } 5707 if (r) { 5708 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5709 PetscCheckSameComm(mat, 1, r, 3); 5710 } 5711 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5712 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5713 MatCheckPreallocated(mat, 1); 5714 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5715 5716 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5717 PetscUseTypeMethod(mat, diagonalscale, l, r); 5718 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5719 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5720 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5721 PetscFunctionReturn(PETSC_SUCCESS); 5722 } 5723 5724 /*@ 5725 MatScale - Scales all elements of a matrix by a given number. 5726 5727 Logically Collective 5728 5729 Input Parameters: 5730 + mat - the matrix to be scaled 5731 - a - the scaling value 5732 5733 Level: intermediate 5734 5735 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5736 @*/ 5737 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5738 { 5739 PetscFunctionBegin; 5740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5741 PetscValidType(mat, 1); 5742 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5743 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5744 PetscValidLogicalCollectiveScalar(mat, a, 2); 5745 MatCheckPreallocated(mat, 1); 5746 5747 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5748 if (a != (PetscScalar)1.0) { 5749 PetscUseTypeMethod(mat, scale, a); 5750 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5751 } 5752 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5753 PetscFunctionReturn(PETSC_SUCCESS); 5754 } 5755 5756 /*@ 5757 MatNorm - Calculates various norms of a matrix. 5758 5759 Collective 5760 5761 Input Parameters: 5762 + mat - the matrix 5763 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5764 5765 Output Parameter: 5766 . nrm - the resulting norm 5767 5768 Level: intermediate 5769 5770 .seealso: [](ch_matrices), `Mat` 5771 @*/ 5772 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5773 { 5774 PetscFunctionBegin; 5775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5776 PetscValidType(mat, 1); 5777 PetscAssertPointer(nrm, 3); 5778 5779 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5780 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5781 MatCheckPreallocated(mat, 1); 5782 5783 PetscUseTypeMethod(mat, norm, type, nrm); 5784 PetscFunctionReturn(PETSC_SUCCESS); 5785 } 5786 5787 /* 5788 This variable is used to prevent counting of MatAssemblyBegin() that 5789 are called from within a MatAssemblyEnd(). 5790 */ 5791 static PetscInt MatAssemblyEnd_InUse = 0; 5792 /*@ 5793 MatAssemblyBegin - Begins assembling the matrix. This routine should 5794 be called after completing all calls to `MatSetValues()`. 5795 5796 Collective 5797 5798 Input Parameters: 5799 + mat - the matrix 5800 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5801 5802 Level: beginner 5803 5804 Notes: 5805 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5806 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5807 5808 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5809 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5810 using the matrix. 5811 5812 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5813 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 5814 a global collective operation requiring all processes that share the matrix. 5815 5816 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5817 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5818 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5819 5820 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5821 @*/ 5822 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5823 { 5824 PetscFunctionBegin; 5825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5826 PetscValidType(mat, 1); 5827 MatCheckPreallocated(mat, 1); 5828 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5829 if (mat->assembled) { 5830 mat->was_assembled = PETSC_TRUE; 5831 mat->assembled = PETSC_FALSE; 5832 } 5833 5834 if (!MatAssemblyEnd_InUse) { 5835 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5836 PetscTryTypeMethod(mat, assemblybegin, type); 5837 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5838 } else PetscTryTypeMethod(mat, assemblybegin, type); 5839 PetscFunctionReturn(PETSC_SUCCESS); 5840 } 5841 5842 /*@ 5843 MatAssembled - Indicates if a matrix has been assembled and is ready for 5844 use; for example, in matrix-vector product. 5845 5846 Not Collective 5847 5848 Input Parameter: 5849 . mat - the matrix 5850 5851 Output Parameter: 5852 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5853 5854 Level: advanced 5855 5856 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5857 @*/ 5858 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5859 { 5860 PetscFunctionBegin; 5861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5862 PetscAssertPointer(assembled, 2); 5863 *assembled = mat->assembled; 5864 PetscFunctionReturn(PETSC_SUCCESS); 5865 } 5866 5867 /*@ 5868 MatAssemblyEnd - Completes assembling the matrix. This routine should 5869 be called after `MatAssemblyBegin()`. 5870 5871 Collective 5872 5873 Input Parameters: 5874 + mat - the matrix 5875 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5876 5877 Options Database Keys: 5878 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5879 . -mat_view ::ascii_info_detail - Prints more detailed info 5880 . -mat_view - Prints matrix in ASCII format 5881 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5882 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5883 . -display <name> - Sets display name (default is host) 5884 . -draw_pause <sec> - Sets number of seconds to pause after display 5885 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5886 . -viewer_socket_machine <machine> - Machine to use for socket 5887 . -viewer_socket_port <port> - Port number to use for socket 5888 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5889 5890 Level: beginner 5891 5892 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5893 @*/ 5894 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5895 { 5896 static PetscInt inassm = 0; 5897 PetscBool flg = PETSC_FALSE; 5898 5899 PetscFunctionBegin; 5900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5901 PetscValidType(mat, 1); 5902 5903 inassm++; 5904 MatAssemblyEnd_InUse++; 5905 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5906 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5907 PetscTryTypeMethod(mat, assemblyend, type); 5908 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5909 } else PetscTryTypeMethod(mat, assemblyend, type); 5910 5911 /* Flush assembly is not a true assembly */ 5912 if (type != MAT_FLUSH_ASSEMBLY) { 5913 if (mat->num_ass) { 5914 if (!mat->symmetry_eternal) { 5915 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5916 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5917 } 5918 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5919 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5920 } 5921 mat->num_ass++; 5922 mat->assembled = PETSC_TRUE; 5923 mat->ass_nonzerostate = mat->nonzerostate; 5924 } 5925 5926 mat->insertmode = NOT_SET_VALUES; 5927 MatAssemblyEnd_InUse--; 5928 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5929 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5930 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5931 5932 if (mat->checksymmetryonassembly) { 5933 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5934 if (flg) { 5935 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5936 } else { 5937 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5938 } 5939 } 5940 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5941 } 5942 inassm--; 5943 PetscFunctionReturn(PETSC_SUCCESS); 5944 } 5945 5946 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5947 /*@ 5948 MatSetOption - Sets a parameter option for a matrix. Some options 5949 may be specific to certain storage formats. Some options 5950 determine how values will be inserted (or added). Sorted, 5951 row-oriented input will generally assemble the fastest. The default 5952 is row-oriented. 5953 5954 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5955 5956 Input Parameters: 5957 + mat - the matrix 5958 . op - the option, one of those listed below (and possibly others), 5959 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5960 5961 Options Describing Matrix Structure: 5962 + `MAT_SPD` - symmetric positive definite 5963 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5964 . `MAT_HERMITIAN` - transpose is the complex conjugation 5965 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5966 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5967 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5968 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5969 5970 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5971 do not need to be computed (usually at a high cost) 5972 5973 Options For Use with `MatSetValues()`: 5974 Insert a logically dense subblock, which can be 5975 . `MAT_ROW_ORIENTED` - row-oriented (default) 5976 5977 These options reflect the data you pass in with `MatSetValues()`; it has 5978 nothing to do with how the data is stored internally in the matrix 5979 data structure. 5980 5981 When (re)assembling a matrix, we can restrict the input for 5982 efficiency/debugging purposes. These options include 5983 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5984 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5985 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5986 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5987 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5988 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5989 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5990 performance for very large process counts. 5991 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5992 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5993 functions, instead sending only neighbor messages. 5994 5995 Level: intermediate 5996 5997 Notes: 5998 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5999 6000 Some options are relevant only for particular matrix types and 6001 are thus ignored by others. Other options are not supported by 6002 certain matrix types and will generate an error message if set. 6003 6004 If using Fortran to compute a matrix, one may need to 6005 use the column-oriented option (or convert to the row-oriented 6006 format). 6007 6008 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6009 that would generate a new entry in the nonzero structure is instead 6010 ignored. Thus, if memory has not already been allocated for this particular 6011 data, then the insertion is ignored. For dense matrices, in which 6012 the entire array is allocated, no entries are ever ignored. 6013 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6014 6015 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6016 that would generate a new entry in the nonzero structure instead produces 6017 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 6018 6019 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6020 that would generate a new entry that has not been preallocated will 6021 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6022 only.) This is a useful flag when debugging matrix memory preallocation. 6023 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6024 6025 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6026 other processors should be dropped, rather than stashed. 6027 This is useful if you know that the "owning" processor is also 6028 always generating the correct matrix entries, so that PETSc need 6029 not transfer duplicate entries generated on another processor. 6030 6031 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6032 searches during matrix assembly. When this flag is set, the hash table 6033 is created during the first matrix assembly. This hash table is 6034 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6035 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6036 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6037 supported by `MATMPIBAIJ` format only. 6038 6039 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6040 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6041 6042 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6043 a zero location in the matrix 6044 6045 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6046 6047 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6048 zero row routines and thus improves performance for very large process counts. 6049 6050 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6051 part of the matrix (since they should match the upper triangular part). 6052 6053 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6054 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6055 with finite difference schemes with non-periodic boundary conditions. 6056 6057 Developer Note: 6058 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6059 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6060 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6061 not changed. 6062 6063 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6064 @*/ 6065 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6066 { 6067 PetscFunctionBegin; 6068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6069 if (op > 0) { 6070 PetscValidLogicalCollectiveEnum(mat, op, 2); 6071 PetscValidLogicalCollectiveBool(mat, flg, 3); 6072 } 6073 6074 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); 6075 6076 switch (op) { 6077 case MAT_FORCE_DIAGONAL_ENTRIES: 6078 mat->force_diagonals = flg; 6079 PetscFunctionReturn(PETSC_SUCCESS); 6080 case MAT_NO_OFF_PROC_ENTRIES: 6081 mat->nooffprocentries = flg; 6082 PetscFunctionReturn(PETSC_SUCCESS); 6083 case MAT_SUBSET_OFF_PROC_ENTRIES: 6084 mat->assembly_subset = flg; 6085 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6086 #if !defined(PETSC_HAVE_MPIUNI) 6087 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6088 #endif 6089 mat->stash.first_assembly_done = PETSC_FALSE; 6090 } 6091 PetscFunctionReturn(PETSC_SUCCESS); 6092 case MAT_NO_OFF_PROC_ZERO_ROWS: 6093 mat->nooffproczerorows = flg; 6094 PetscFunctionReturn(PETSC_SUCCESS); 6095 case MAT_SPD: 6096 if (flg) { 6097 mat->spd = PETSC_BOOL3_TRUE; 6098 mat->symmetric = PETSC_BOOL3_TRUE; 6099 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6100 } else { 6101 mat->spd = PETSC_BOOL3_FALSE; 6102 } 6103 break; 6104 case MAT_SYMMETRIC: 6105 mat->symmetric = PetscBoolToBool3(flg); 6106 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6107 #if !defined(PETSC_USE_COMPLEX) 6108 mat->hermitian = PetscBoolToBool3(flg); 6109 #endif 6110 break; 6111 case MAT_HERMITIAN: 6112 mat->hermitian = PetscBoolToBool3(flg); 6113 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6114 #if !defined(PETSC_USE_COMPLEX) 6115 mat->symmetric = PetscBoolToBool3(flg); 6116 #endif 6117 break; 6118 case MAT_STRUCTURALLY_SYMMETRIC: 6119 mat->structurally_symmetric = PetscBoolToBool3(flg); 6120 break; 6121 case MAT_SYMMETRY_ETERNAL: 6122 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"); 6123 mat->symmetry_eternal = flg; 6124 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6125 break; 6126 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6127 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"); 6128 mat->structural_symmetry_eternal = flg; 6129 break; 6130 case MAT_SPD_ETERNAL: 6131 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"); 6132 mat->spd_eternal = flg; 6133 if (flg) { 6134 mat->structural_symmetry_eternal = PETSC_TRUE; 6135 mat->symmetry_eternal = PETSC_TRUE; 6136 } 6137 break; 6138 case MAT_STRUCTURE_ONLY: 6139 mat->structure_only = flg; 6140 break; 6141 case MAT_SORTED_FULL: 6142 mat->sortedfull = flg; 6143 break; 6144 default: 6145 break; 6146 } 6147 PetscTryTypeMethod(mat, setoption, op, flg); 6148 PetscFunctionReturn(PETSC_SUCCESS); 6149 } 6150 6151 /*@ 6152 MatGetOption - Gets a parameter option that has been set for a matrix. 6153 6154 Logically Collective 6155 6156 Input Parameters: 6157 + mat - the matrix 6158 - op - the option, this only responds to certain options, check the code for which ones 6159 6160 Output Parameter: 6161 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6162 6163 Level: intermediate 6164 6165 Notes: 6166 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6167 6168 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6169 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6170 6171 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6172 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6173 @*/ 6174 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6175 { 6176 PetscFunctionBegin; 6177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6178 PetscValidType(mat, 1); 6179 6180 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); 6181 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()"); 6182 6183 switch (op) { 6184 case MAT_NO_OFF_PROC_ENTRIES: 6185 *flg = mat->nooffprocentries; 6186 break; 6187 case MAT_NO_OFF_PROC_ZERO_ROWS: 6188 *flg = mat->nooffproczerorows; 6189 break; 6190 case MAT_SYMMETRIC: 6191 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6192 break; 6193 case MAT_HERMITIAN: 6194 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6195 break; 6196 case MAT_STRUCTURALLY_SYMMETRIC: 6197 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6198 break; 6199 case MAT_SPD: 6200 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6201 break; 6202 case MAT_SYMMETRY_ETERNAL: 6203 *flg = mat->symmetry_eternal; 6204 break; 6205 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6206 *flg = mat->symmetry_eternal; 6207 break; 6208 default: 6209 break; 6210 } 6211 PetscFunctionReturn(PETSC_SUCCESS); 6212 } 6213 6214 /*@ 6215 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6216 this routine retains the old nonzero structure. 6217 6218 Logically Collective 6219 6220 Input Parameter: 6221 . mat - the matrix 6222 6223 Level: intermediate 6224 6225 Note: 6226 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. 6227 See the Performance chapter of the users manual for information on preallocating matrices. 6228 6229 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6230 @*/ 6231 PetscErrorCode MatZeroEntries(Mat mat) 6232 { 6233 PetscFunctionBegin; 6234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6235 PetscValidType(mat, 1); 6236 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6237 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"); 6238 MatCheckPreallocated(mat, 1); 6239 6240 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6241 PetscUseTypeMethod(mat, zeroentries); 6242 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6243 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6244 PetscFunctionReturn(PETSC_SUCCESS); 6245 } 6246 6247 /*@ 6248 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6249 of a set of rows and columns of a matrix. 6250 6251 Collective 6252 6253 Input Parameters: 6254 + mat - the matrix 6255 . numRows - the number of rows/columns to zero 6256 . rows - the global row indices 6257 . diag - value put in the diagonal of the eliminated rows 6258 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6259 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6260 6261 Level: intermediate 6262 6263 Notes: 6264 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6265 6266 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6267 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 6268 6269 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6270 Krylov method to take advantage of the known solution on the zeroed rows. 6271 6272 For the parallel case, all processes that share the matrix (i.e., 6273 those in the communicator used for matrix creation) MUST call this 6274 routine, regardless of whether any rows being zeroed are owned by 6275 them. 6276 6277 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6278 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 6279 missing. 6280 6281 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6282 list only rows local to itself). 6283 6284 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6285 6286 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6287 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6288 @*/ 6289 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6290 { 6291 PetscFunctionBegin; 6292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6293 PetscValidType(mat, 1); 6294 if (numRows) PetscAssertPointer(rows, 3); 6295 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6296 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6297 MatCheckPreallocated(mat, 1); 6298 6299 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6300 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6301 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6302 PetscFunctionReturn(PETSC_SUCCESS); 6303 } 6304 6305 /*@ 6306 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6307 of a set of rows and columns of a matrix. 6308 6309 Collective 6310 6311 Input Parameters: 6312 + mat - the matrix 6313 . is - the rows to zero 6314 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6315 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6316 - b - optional vector of right-hand side, that will be adjusted by provided solution 6317 6318 Level: intermediate 6319 6320 Note: 6321 See `MatZeroRowsColumns()` for details on how this routine operates. 6322 6323 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6324 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6325 @*/ 6326 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6327 { 6328 PetscInt numRows; 6329 const PetscInt *rows; 6330 6331 PetscFunctionBegin; 6332 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6333 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6334 PetscValidType(mat, 1); 6335 PetscValidType(is, 2); 6336 PetscCall(ISGetLocalSize(is, &numRows)); 6337 PetscCall(ISGetIndices(is, &rows)); 6338 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6339 PetscCall(ISRestoreIndices(is, &rows)); 6340 PetscFunctionReturn(PETSC_SUCCESS); 6341 } 6342 6343 /*@ 6344 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6345 of a set of rows of a matrix. 6346 6347 Collective 6348 6349 Input Parameters: 6350 + mat - the matrix 6351 . numRows - the number of rows to zero 6352 . rows - the global row indices 6353 . diag - value put in the diagonal of the zeroed rows 6354 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6355 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6356 6357 Level: intermediate 6358 6359 Notes: 6360 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6361 6362 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6363 6364 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6365 Krylov method to take advantage of the known solution on the zeroed rows. 6366 6367 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) 6368 from the matrix. 6369 6370 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6371 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6372 formats this does not alter the nonzero structure. 6373 6374 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6375 of the matrix is not changed the values are 6376 merely zeroed. 6377 6378 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6379 formats can optionally remove the main diagonal entry from the 6380 nonzero structure as well, by passing 0.0 as the final argument). 6381 6382 For the parallel case, all processes that share the matrix (i.e., 6383 those in the communicator used for matrix creation) MUST call this 6384 routine, regardless of whether any rows being zeroed are owned by 6385 them. 6386 6387 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6388 list only rows local to itself). 6389 6390 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6391 owns that are to be zeroed. This saves a global synchronization in the implementation. 6392 6393 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6394 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6395 @*/ 6396 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6397 { 6398 PetscFunctionBegin; 6399 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6400 PetscValidType(mat, 1); 6401 if (numRows) PetscAssertPointer(rows, 3); 6402 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6403 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6404 MatCheckPreallocated(mat, 1); 6405 6406 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6407 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6408 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6409 PetscFunctionReturn(PETSC_SUCCESS); 6410 } 6411 6412 /*@ 6413 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6414 of a set of rows of a matrix indicated by an `IS` 6415 6416 Collective 6417 6418 Input Parameters: 6419 + mat - the matrix 6420 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6421 . diag - value put in all diagonals of eliminated rows 6422 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6423 - b - optional vector of right-hand side, that will be adjusted by provided solution 6424 6425 Level: intermediate 6426 6427 Note: 6428 See `MatZeroRows()` for details on how this routine operates. 6429 6430 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6431 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6432 @*/ 6433 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6434 { 6435 PetscInt numRows = 0; 6436 const PetscInt *rows = NULL; 6437 6438 PetscFunctionBegin; 6439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6440 PetscValidType(mat, 1); 6441 if (is) { 6442 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6443 PetscCall(ISGetLocalSize(is, &numRows)); 6444 PetscCall(ISGetIndices(is, &rows)); 6445 } 6446 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6447 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6448 PetscFunctionReturn(PETSC_SUCCESS); 6449 } 6450 6451 /*@ 6452 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6453 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6454 6455 Collective 6456 6457 Input Parameters: 6458 + mat - the matrix 6459 . numRows - the number of rows to remove 6460 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6461 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6462 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6463 - b - optional vector of right-hand side, that will be adjusted by provided solution 6464 6465 Level: intermediate 6466 6467 Notes: 6468 See `MatZeroRows()` for details on how this routine operates. 6469 6470 The grid coordinates are across the entire grid, not just the local portion 6471 6472 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6473 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6474 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6475 `DM_BOUNDARY_PERIODIC` boundary type. 6476 6477 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 6478 a single value per point) you can skip filling those indices. 6479 6480 Fortran Note: 6481 `idxm` and `idxn` should be declared as 6482 $ MatStencil idxm(4, m) 6483 and the values inserted using 6484 .vb 6485 idxm(MatStencil_i, 1) = i 6486 idxm(MatStencil_j, 1) = j 6487 idxm(MatStencil_k, 1) = k 6488 idxm(MatStencil_c, 1) = c 6489 etc 6490 .ve 6491 6492 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6493 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6494 @*/ 6495 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6496 { 6497 PetscInt dim = mat->stencil.dim; 6498 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6499 PetscInt *dims = mat->stencil.dims + 1; 6500 PetscInt *starts = mat->stencil.starts; 6501 PetscInt *dxm = (PetscInt *)rows; 6502 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6503 6504 PetscFunctionBegin; 6505 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6506 PetscValidType(mat, 1); 6507 if (numRows) PetscAssertPointer(rows, 3); 6508 6509 PetscCall(PetscMalloc1(numRows, &jdxm)); 6510 for (i = 0; i < numRows; ++i) { 6511 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6512 for (j = 0; j < 3 - sdim; ++j) dxm++; 6513 /* Local index in X dir */ 6514 tmp = *dxm++ - starts[0]; 6515 /* Loop over remaining dimensions */ 6516 for (j = 0; j < dim - 1; ++j) { 6517 /* If nonlocal, set index to be negative */ 6518 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6519 /* Update local index */ 6520 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6521 } 6522 /* Skip component slot if necessary */ 6523 if (mat->stencil.noc) dxm++; 6524 /* Local row number */ 6525 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6526 } 6527 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6528 PetscCall(PetscFree(jdxm)); 6529 PetscFunctionReturn(PETSC_SUCCESS); 6530 } 6531 6532 /*@ 6533 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6534 of a set of rows and columns of a matrix. 6535 6536 Collective 6537 6538 Input Parameters: 6539 + mat - the matrix 6540 . numRows - the number of rows/columns to remove 6541 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6542 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6543 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6544 - b - optional vector of right-hand side, that will be adjusted by provided solution 6545 6546 Level: intermediate 6547 6548 Notes: 6549 See `MatZeroRowsColumns()` for details on how this routine operates. 6550 6551 The grid coordinates are across the entire grid, not just the local portion 6552 6553 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6554 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6555 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6556 `DM_BOUNDARY_PERIODIC` boundary type. 6557 6558 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 6559 a single value per point) you can skip filling those indices. 6560 6561 Fortran Note: 6562 `idxm` and `idxn` should be declared as 6563 $ MatStencil idxm(4, m) 6564 and the values inserted using 6565 .vb 6566 idxm(MatStencil_i, 1) = i 6567 idxm(MatStencil_j, 1) = j 6568 idxm(MatStencil_k, 1) = k 6569 idxm(MatStencil_c, 1) = c 6570 etc 6571 .ve 6572 6573 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6574 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6575 @*/ 6576 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6577 { 6578 PetscInt dim = mat->stencil.dim; 6579 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6580 PetscInt *dims = mat->stencil.dims + 1; 6581 PetscInt *starts = mat->stencil.starts; 6582 PetscInt *dxm = (PetscInt *)rows; 6583 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6584 6585 PetscFunctionBegin; 6586 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6587 PetscValidType(mat, 1); 6588 if (numRows) PetscAssertPointer(rows, 3); 6589 6590 PetscCall(PetscMalloc1(numRows, &jdxm)); 6591 for (i = 0; i < numRows; ++i) { 6592 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6593 for (j = 0; j < 3 - sdim; ++j) dxm++; 6594 /* Local index in X dir */ 6595 tmp = *dxm++ - starts[0]; 6596 /* Loop over remaining dimensions */ 6597 for (j = 0; j < dim - 1; ++j) { 6598 /* If nonlocal, set index to be negative */ 6599 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6600 /* Update local index */ 6601 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6602 } 6603 /* Skip component slot if necessary */ 6604 if (mat->stencil.noc) dxm++; 6605 /* Local row number */ 6606 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6607 } 6608 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6609 PetscCall(PetscFree(jdxm)); 6610 PetscFunctionReturn(PETSC_SUCCESS); 6611 } 6612 6613 /*@ 6614 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6615 of a set of rows of a matrix; using local numbering of rows. 6616 6617 Collective 6618 6619 Input Parameters: 6620 + mat - the matrix 6621 . numRows - the number of rows to remove 6622 . rows - the local row indices 6623 . diag - value put in all diagonals of eliminated rows 6624 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6625 - b - optional vector of right-hand side, that will be adjusted by provided solution 6626 6627 Level: intermediate 6628 6629 Notes: 6630 Before calling `MatZeroRowsLocal()`, the user must first set the 6631 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6632 6633 See `MatZeroRows()` for details on how this routine operates. 6634 6635 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6636 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6637 @*/ 6638 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6639 { 6640 PetscFunctionBegin; 6641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6642 PetscValidType(mat, 1); 6643 if (numRows) PetscAssertPointer(rows, 3); 6644 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6645 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6646 MatCheckPreallocated(mat, 1); 6647 6648 if (mat->ops->zerorowslocal) { 6649 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6650 } else { 6651 IS is, newis; 6652 const PetscInt *newRows; 6653 6654 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6655 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6656 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6657 PetscCall(ISGetIndices(newis, &newRows)); 6658 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6659 PetscCall(ISRestoreIndices(newis, &newRows)); 6660 PetscCall(ISDestroy(&newis)); 6661 PetscCall(ISDestroy(&is)); 6662 } 6663 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6664 PetscFunctionReturn(PETSC_SUCCESS); 6665 } 6666 6667 /*@ 6668 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6669 of a set of rows of a matrix; using local numbering of rows. 6670 6671 Collective 6672 6673 Input Parameters: 6674 + mat - the matrix 6675 . is - index set of rows to remove 6676 . diag - value put in all diagonals of eliminated rows 6677 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6678 - b - optional vector of right-hand side, that will be adjusted by provided solution 6679 6680 Level: intermediate 6681 6682 Notes: 6683 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6684 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6685 6686 See `MatZeroRows()` for details on how this routine operates. 6687 6688 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6689 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6690 @*/ 6691 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6692 { 6693 PetscInt numRows; 6694 const PetscInt *rows; 6695 6696 PetscFunctionBegin; 6697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6698 PetscValidType(mat, 1); 6699 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6702 MatCheckPreallocated(mat, 1); 6703 6704 PetscCall(ISGetLocalSize(is, &numRows)); 6705 PetscCall(ISGetIndices(is, &rows)); 6706 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6707 PetscCall(ISRestoreIndices(is, &rows)); 6708 PetscFunctionReturn(PETSC_SUCCESS); 6709 } 6710 6711 /*@ 6712 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6713 of a set of rows and columns of a matrix; using local numbering of rows. 6714 6715 Collective 6716 6717 Input Parameters: 6718 + mat - the matrix 6719 . numRows - the number of rows to remove 6720 . rows - the global row indices 6721 . diag - value put in all diagonals of eliminated rows 6722 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6723 - b - optional vector of right-hand side, that will be adjusted by provided solution 6724 6725 Level: intermediate 6726 6727 Notes: 6728 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6729 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6730 6731 See `MatZeroRowsColumns()` for details on how this routine operates. 6732 6733 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6734 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6735 @*/ 6736 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6737 { 6738 IS is, newis; 6739 const PetscInt *newRows; 6740 6741 PetscFunctionBegin; 6742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6743 PetscValidType(mat, 1); 6744 if (numRows) PetscAssertPointer(rows, 3); 6745 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6746 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6747 MatCheckPreallocated(mat, 1); 6748 6749 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6750 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6751 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6752 PetscCall(ISGetIndices(newis, &newRows)); 6753 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6754 PetscCall(ISRestoreIndices(newis, &newRows)); 6755 PetscCall(ISDestroy(&newis)); 6756 PetscCall(ISDestroy(&is)); 6757 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6758 PetscFunctionReturn(PETSC_SUCCESS); 6759 } 6760 6761 /*@ 6762 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6763 of a set of rows and columns of a matrix; using local numbering of rows. 6764 6765 Collective 6766 6767 Input Parameters: 6768 + mat - the matrix 6769 . is - index set of rows to remove 6770 . diag - value put in all diagonals of eliminated rows 6771 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6772 - b - optional vector of right-hand side, that will be adjusted by provided solution 6773 6774 Level: intermediate 6775 6776 Notes: 6777 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6778 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6779 6780 See `MatZeroRowsColumns()` for details on how this routine operates. 6781 6782 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6783 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6784 @*/ 6785 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6786 { 6787 PetscInt numRows; 6788 const PetscInt *rows; 6789 6790 PetscFunctionBegin; 6791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6792 PetscValidType(mat, 1); 6793 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6794 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6795 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6796 MatCheckPreallocated(mat, 1); 6797 6798 PetscCall(ISGetLocalSize(is, &numRows)); 6799 PetscCall(ISGetIndices(is, &rows)); 6800 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6801 PetscCall(ISRestoreIndices(is, &rows)); 6802 PetscFunctionReturn(PETSC_SUCCESS); 6803 } 6804 6805 /*@ 6806 MatGetSize - Returns the numbers of rows and columns in a matrix. 6807 6808 Not Collective 6809 6810 Input Parameter: 6811 . mat - the matrix 6812 6813 Output Parameters: 6814 + m - the number of global rows 6815 - n - the number of global columns 6816 6817 Level: beginner 6818 6819 Note: 6820 Both output parameters can be `NULL` on input. 6821 6822 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6823 @*/ 6824 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6825 { 6826 PetscFunctionBegin; 6827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6828 if (m) *m = mat->rmap->N; 6829 if (n) *n = mat->cmap->N; 6830 PetscFunctionReturn(PETSC_SUCCESS); 6831 } 6832 6833 /*@ 6834 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6835 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6836 6837 Not Collective 6838 6839 Input Parameter: 6840 . mat - the matrix 6841 6842 Output Parameters: 6843 + m - the number of local rows, use `NULL` to not obtain this value 6844 - n - the number of local columns, use `NULL` to not obtain this value 6845 6846 Level: beginner 6847 6848 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6849 @*/ 6850 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6851 { 6852 PetscFunctionBegin; 6853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6854 if (m) PetscAssertPointer(m, 2); 6855 if (n) PetscAssertPointer(n, 3); 6856 if (m) *m = mat->rmap->n; 6857 if (n) *n = mat->cmap->n; 6858 PetscFunctionReturn(PETSC_SUCCESS); 6859 } 6860 6861 /*@ 6862 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6863 vector one multiplies this matrix by that are owned by this processor. 6864 6865 Not Collective, unless matrix has not been allocated, then collective 6866 6867 Input Parameter: 6868 . mat - the matrix 6869 6870 Output Parameters: 6871 + m - the global index of the first local column, use `NULL` to not obtain this value 6872 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6873 6874 Level: developer 6875 6876 Notes: 6877 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6878 6879 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6880 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6881 6882 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6883 the local values in the matrix. 6884 6885 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6886 Layouts](sec_matlayout) for details on matrix layouts. 6887 6888 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6889 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6890 @*/ 6891 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6892 { 6893 PetscFunctionBegin; 6894 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6895 PetscValidType(mat, 1); 6896 if (m) PetscAssertPointer(m, 2); 6897 if (n) PetscAssertPointer(n, 3); 6898 MatCheckPreallocated(mat, 1); 6899 if (m) *m = mat->cmap->rstart; 6900 if (n) *n = mat->cmap->rend; 6901 PetscFunctionReturn(PETSC_SUCCESS); 6902 } 6903 6904 /*@ 6905 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6906 this MPI process. 6907 6908 Not Collective 6909 6910 Input Parameter: 6911 . mat - the matrix 6912 6913 Output Parameters: 6914 + m - the global index of the first local row, use `NULL` to not obtain this value 6915 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6916 6917 Level: beginner 6918 6919 Notes: 6920 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6921 6922 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6923 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6924 6925 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6926 the local values in the matrix. 6927 6928 The high argument is one more than the last element stored locally. 6929 6930 For all matrices it returns the range of matrix rows associated with rows of a vector that 6931 would contain the result of a matrix vector product with this matrix. See [Matrix 6932 Layouts](sec_matlayout) for details on matrix layouts. 6933 6934 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6935 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6936 @*/ 6937 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6938 { 6939 PetscFunctionBegin; 6940 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6941 PetscValidType(mat, 1); 6942 if (m) PetscAssertPointer(m, 2); 6943 if (n) PetscAssertPointer(n, 3); 6944 MatCheckPreallocated(mat, 1); 6945 if (m) *m = mat->rmap->rstart; 6946 if (n) *n = mat->rmap->rend; 6947 PetscFunctionReturn(PETSC_SUCCESS); 6948 } 6949 6950 /*@C 6951 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6952 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6953 6954 Not Collective, unless matrix has not been allocated 6955 6956 Input Parameter: 6957 . mat - the matrix 6958 6959 Output Parameter: 6960 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6961 where `size` is the number of MPI processes used by `mat` 6962 6963 Level: beginner 6964 6965 Notes: 6966 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6967 6968 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6969 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6970 6971 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6972 the local values in the matrix. 6973 6974 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6975 would contain the result of a matrix vector product with this matrix. See [Matrix 6976 Layouts](sec_matlayout) for details on matrix layouts. 6977 6978 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6979 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6980 `DMDAGetGhostCorners()`, `DM` 6981 @*/ 6982 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6983 { 6984 PetscFunctionBegin; 6985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6986 PetscValidType(mat, 1); 6987 MatCheckPreallocated(mat, 1); 6988 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6989 PetscFunctionReturn(PETSC_SUCCESS); 6990 } 6991 6992 /*@C 6993 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6994 vector one multiplies this vector by that are owned by each processor. 6995 6996 Not Collective, unless matrix has not been allocated 6997 6998 Input Parameter: 6999 . mat - the matrix 7000 7001 Output Parameter: 7002 . ranges - start of each processors portion plus one more than the total length at the end 7003 7004 Level: beginner 7005 7006 Notes: 7007 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7008 7009 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7010 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7011 7012 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7013 the local values in the matrix. 7014 7015 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7016 Layouts](sec_matlayout) for details on matrix layouts. 7017 7018 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7019 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7020 `DMDAGetGhostCorners()`, `DM` 7021 @*/ 7022 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7023 { 7024 PetscFunctionBegin; 7025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7026 PetscValidType(mat, 1); 7027 MatCheckPreallocated(mat, 1); 7028 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7029 PetscFunctionReturn(PETSC_SUCCESS); 7030 } 7031 7032 /*@ 7033 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7034 7035 Not Collective 7036 7037 Input Parameter: 7038 . A - matrix 7039 7040 Output Parameters: 7041 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7042 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7043 7044 Level: intermediate 7045 7046 Note: 7047 You should call `ISDestroy()` on the returned `IS` 7048 7049 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7050 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7051 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7052 details on matrix layouts. 7053 7054 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7055 @*/ 7056 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7057 { 7058 PetscErrorCode (*f)(Mat, IS *, IS *); 7059 7060 PetscFunctionBegin; 7061 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7062 PetscValidType(A, 1); 7063 MatCheckPreallocated(A, 1); 7064 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7065 if (f) { 7066 PetscCall((*f)(A, rows, cols)); 7067 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7068 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7069 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7070 } 7071 PetscFunctionReturn(PETSC_SUCCESS); 7072 } 7073 7074 /*@ 7075 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7076 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7077 to complete the factorization. 7078 7079 Collective 7080 7081 Input Parameters: 7082 + fact - the factorized matrix obtained with `MatGetFactor()` 7083 . mat - the matrix 7084 . row - row permutation 7085 . col - column permutation 7086 - info - structure containing 7087 .vb 7088 levels - number of levels of fill. 7089 expected fill - as ratio of original fill. 7090 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7091 missing diagonal entries) 7092 .ve 7093 7094 Level: developer 7095 7096 Notes: 7097 See [Matrix Factorization](sec_matfactor) for additional information. 7098 7099 Most users should employ the `KSP` interface for linear solvers 7100 instead of working directly with matrix algebra routines such as this. 7101 See, e.g., `KSPCreate()`. 7102 7103 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7104 7105 Developer Note: 7106 The Fortran interface is not autogenerated as the 7107 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7108 7109 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7110 `MatGetOrdering()`, `MatFactorInfo` 7111 @*/ 7112 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7113 { 7114 PetscFunctionBegin; 7115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7116 PetscValidType(mat, 2); 7117 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7118 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7119 PetscAssertPointer(info, 5); 7120 PetscAssertPointer(fact, 1); 7121 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7122 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7123 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7124 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7125 MatCheckPreallocated(mat, 2); 7126 7127 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7128 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7129 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7130 PetscFunctionReturn(PETSC_SUCCESS); 7131 } 7132 7133 /*@ 7134 MatICCFactorSymbolic - Performs symbolic incomplete 7135 Cholesky factorization for a symmetric matrix. Use 7136 `MatCholeskyFactorNumeric()` to complete the factorization. 7137 7138 Collective 7139 7140 Input Parameters: 7141 + fact - the factorized matrix obtained with `MatGetFactor()` 7142 . mat - the matrix to be factored 7143 . perm - row and column permutation 7144 - info - structure containing 7145 .vb 7146 levels - number of levels of fill. 7147 expected fill - as ratio of original fill. 7148 .ve 7149 7150 Level: developer 7151 7152 Notes: 7153 Most users should employ the `KSP` interface for linear solvers 7154 instead of working directly with matrix algebra routines such as this. 7155 See, e.g., `KSPCreate()`. 7156 7157 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7158 7159 Developer Note: 7160 The Fortran interface is not autogenerated as the 7161 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7162 7163 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7164 @*/ 7165 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7166 { 7167 PetscFunctionBegin; 7168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7169 PetscValidType(mat, 2); 7170 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7171 PetscAssertPointer(info, 4); 7172 PetscAssertPointer(fact, 1); 7173 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7174 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7175 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7176 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7177 MatCheckPreallocated(mat, 2); 7178 7179 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7180 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7181 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7182 PetscFunctionReturn(PETSC_SUCCESS); 7183 } 7184 7185 /*@C 7186 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7187 points to an array of valid matrices, they may be reused to store the new 7188 submatrices. 7189 7190 Collective 7191 7192 Input Parameters: 7193 + mat - the matrix 7194 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7195 . irow - index set of rows to extract 7196 . icol - index set of columns to extract 7197 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7198 7199 Output Parameter: 7200 . submat - the array of submatrices 7201 7202 Level: advanced 7203 7204 Notes: 7205 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7206 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7207 to extract a parallel submatrix. 7208 7209 Some matrix types place restrictions on the row and column 7210 indices, such as that they be sorted or that they be equal to each other. 7211 7212 The index sets may not have duplicate entries. 7213 7214 When extracting submatrices from a parallel matrix, each processor can 7215 form a different submatrix by setting the rows and columns of its 7216 individual index sets according to the local submatrix desired. 7217 7218 When finished using the submatrices, the user should destroy 7219 them with `MatDestroySubMatrices()`. 7220 7221 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7222 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7223 7224 This routine creates the matrices in submat; you should NOT create them before 7225 calling it. It also allocates the array of matrix pointers submat. 7226 7227 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7228 request one row/column in a block, they must request all rows/columns that are in 7229 that block. For example, if the block size is 2 you cannot request just row 0 and 7230 column 0. 7231 7232 Fortran Note: 7233 .vb 7234 Mat, pointer :: submat(:) 7235 .ve 7236 7237 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7238 @*/ 7239 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7240 { 7241 PetscInt i; 7242 PetscBool eq; 7243 7244 PetscFunctionBegin; 7245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7246 PetscValidType(mat, 1); 7247 if (n) { 7248 PetscAssertPointer(irow, 3); 7249 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7250 PetscAssertPointer(icol, 4); 7251 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7252 } 7253 PetscAssertPointer(submat, 6); 7254 if (n && scall == MAT_REUSE_MATRIX) { 7255 PetscAssertPointer(*submat, 6); 7256 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7257 } 7258 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7259 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7260 MatCheckPreallocated(mat, 1); 7261 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7262 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7263 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7264 for (i = 0; i < n; i++) { 7265 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7266 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7267 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7268 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7269 if (mat->boundtocpu && mat->bindingpropagates) { 7270 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7271 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7272 } 7273 #endif 7274 } 7275 PetscFunctionReturn(PETSC_SUCCESS); 7276 } 7277 7278 /*@C 7279 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7280 7281 Collective 7282 7283 Input Parameters: 7284 + mat - the matrix 7285 . n - the number of submatrixes to be extracted 7286 . irow - index set of rows to extract 7287 . icol - index set of columns to extract 7288 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7289 7290 Output Parameter: 7291 . submat - the array of submatrices 7292 7293 Level: advanced 7294 7295 Note: 7296 This is used by `PCGASM` 7297 7298 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7299 @*/ 7300 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7301 { 7302 PetscInt i; 7303 PetscBool eq; 7304 7305 PetscFunctionBegin; 7306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7307 PetscValidType(mat, 1); 7308 if (n) { 7309 PetscAssertPointer(irow, 3); 7310 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7311 PetscAssertPointer(icol, 4); 7312 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7313 } 7314 PetscAssertPointer(submat, 6); 7315 if (n && scall == MAT_REUSE_MATRIX) { 7316 PetscAssertPointer(*submat, 6); 7317 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7318 } 7319 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7320 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7321 MatCheckPreallocated(mat, 1); 7322 7323 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7324 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7325 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7326 for (i = 0; i < n; i++) { 7327 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7328 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7329 } 7330 PetscFunctionReturn(PETSC_SUCCESS); 7331 } 7332 7333 /*@C 7334 MatDestroyMatrices - Destroys an array of matrices 7335 7336 Collective 7337 7338 Input Parameters: 7339 + n - the number of local matrices 7340 - mat - the matrices (this is a pointer to the array of matrices) 7341 7342 Level: advanced 7343 7344 Notes: 7345 Frees not only the matrices, but also the array that contains the matrices 7346 7347 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7348 7349 Fortran Note: 7350 Does not free the `mat` array. 7351 7352 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7353 @*/ 7354 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7355 { 7356 PetscInt i; 7357 7358 PetscFunctionBegin; 7359 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7360 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7361 PetscAssertPointer(mat, 2); 7362 7363 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7364 7365 /* memory is allocated even if n = 0 */ 7366 PetscCall(PetscFree(*mat)); 7367 PetscFunctionReturn(PETSC_SUCCESS); 7368 } 7369 7370 /*@C 7371 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7372 7373 Collective 7374 7375 Input Parameters: 7376 + n - the number of local matrices 7377 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7378 7379 Level: advanced 7380 7381 Note: 7382 Frees not only the matrices, but also the array that contains the matrices 7383 7384 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7385 @*/ 7386 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7387 { 7388 Mat mat0; 7389 7390 PetscFunctionBegin; 7391 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7392 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7393 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7394 PetscAssertPointer(mat, 2); 7395 7396 mat0 = (*mat)[0]; 7397 if (mat0 && mat0->ops->destroysubmatrices) { 7398 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7399 } else { 7400 PetscCall(MatDestroyMatrices(n, mat)); 7401 } 7402 PetscFunctionReturn(PETSC_SUCCESS); 7403 } 7404 7405 /*@ 7406 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7407 7408 Collective 7409 7410 Input Parameter: 7411 . mat - the matrix 7412 7413 Output Parameter: 7414 . matstruct - the sequential matrix with the nonzero structure of `mat` 7415 7416 Level: developer 7417 7418 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7419 @*/ 7420 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7421 { 7422 PetscFunctionBegin; 7423 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7424 PetscAssertPointer(matstruct, 2); 7425 7426 PetscValidType(mat, 1); 7427 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7428 MatCheckPreallocated(mat, 1); 7429 7430 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7431 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7432 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7433 PetscFunctionReturn(PETSC_SUCCESS); 7434 } 7435 7436 /*@C 7437 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7438 7439 Collective 7440 7441 Input Parameter: 7442 . mat - the matrix 7443 7444 Level: advanced 7445 7446 Note: 7447 This is not needed, one can just call `MatDestroy()` 7448 7449 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7450 @*/ 7451 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7452 { 7453 PetscFunctionBegin; 7454 PetscAssertPointer(mat, 1); 7455 PetscCall(MatDestroy(mat)); 7456 PetscFunctionReturn(PETSC_SUCCESS); 7457 } 7458 7459 /*@ 7460 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7461 replaces the index sets by larger ones that represent submatrices with 7462 additional overlap. 7463 7464 Collective 7465 7466 Input Parameters: 7467 + mat - the matrix 7468 . n - the number of index sets 7469 . is - the array of index sets (these index sets will changed during the call) 7470 - ov - the additional overlap requested 7471 7472 Options Database Key: 7473 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7474 7475 Level: developer 7476 7477 Note: 7478 The computed overlap preserves the matrix block sizes when the blocks are square. 7479 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7480 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7481 7482 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7483 @*/ 7484 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7485 { 7486 PetscInt i, bs, cbs; 7487 7488 PetscFunctionBegin; 7489 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7490 PetscValidType(mat, 1); 7491 PetscValidLogicalCollectiveInt(mat, n, 2); 7492 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7493 if (n) { 7494 PetscAssertPointer(is, 3); 7495 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7496 } 7497 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7498 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7499 MatCheckPreallocated(mat, 1); 7500 7501 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7502 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7503 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7504 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7505 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7506 if (bs == cbs) { 7507 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7508 } 7509 PetscFunctionReturn(PETSC_SUCCESS); 7510 } 7511 7512 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7513 7514 /*@ 7515 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7516 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7517 additional overlap. 7518 7519 Collective 7520 7521 Input Parameters: 7522 + mat - the matrix 7523 . n - the number of index sets 7524 . is - the array of index sets (these index sets will changed during the call) 7525 - ov - the additional overlap requested 7526 7527 ` Options Database Key: 7528 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7529 7530 Level: developer 7531 7532 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7533 @*/ 7534 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7535 { 7536 PetscInt i; 7537 7538 PetscFunctionBegin; 7539 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7540 PetscValidType(mat, 1); 7541 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7542 if (n) { 7543 PetscAssertPointer(is, 3); 7544 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7545 } 7546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7547 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7548 MatCheckPreallocated(mat, 1); 7549 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7550 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7551 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7552 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7553 PetscFunctionReturn(PETSC_SUCCESS); 7554 } 7555 7556 /*@ 7557 MatGetBlockSize - Returns the matrix block size. 7558 7559 Not Collective 7560 7561 Input Parameter: 7562 . mat - the matrix 7563 7564 Output Parameter: 7565 . bs - block size 7566 7567 Level: intermediate 7568 7569 Notes: 7570 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7571 7572 If the block size has not been set yet this routine returns 1. 7573 7574 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7575 @*/ 7576 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7577 { 7578 PetscFunctionBegin; 7579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7580 PetscAssertPointer(bs, 2); 7581 *bs = PetscAbs(mat->rmap->bs); 7582 PetscFunctionReturn(PETSC_SUCCESS); 7583 } 7584 7585 /*@ 7586 MatGetBlockSizes - Returns the matrix block row and column sizes. 7587 7588 Not Collective 7589 7590 Input Parameter: 7591 . mat - the matrix 7592 7593 Output Parameters: 7594 + rbs - row block size 7595 - cbs - column block size 7596 7597 Level: intermediate 7598 7599 Notes: 7600 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7601 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7602 7603 If a block size has not been set yet this routine returns 1. 7604 7605 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7606 @*/ 7607 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7608 { 7609 PetscFunctionBegin; 7610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7611 if (rbs) PetscAssertPointer(rbs, 2); 7612 if (cbs) PetscAssertPointer(cbs, 3); 7613 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7614 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7615 PetscFunctionReturn(PETSC_SUCCESS); 7616 } 7617 7618 /*@ 7619 MatSetBlockSize - Sets the matrix block size. 7620 7621 Logically Collective 7622 7623 Input Parameters: 7624 + mat - the matrix 7625 - bs - block size 7626 7627 Level: intermediate 7628 7629 Notes: 7630 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7631 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7632 7633 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7634 is compatible with the matrix local sizes. 7635 7636 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7637 @*/ 7638 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7639 { 7640 PetscFunctionBegin; 7641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7642 PetscValidLogicalCollectiveInt(mat, bs, 2); 7643 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7644 PetscFunctionReturn(PETSC_SUCCESS); 7645 } 7646 7647 typedef struct { 7648 PetscInt n; 7649 IS *is; 7650 Mat *mat; 7651 PetscObjectState nonzerostate; 7652 Mat C; 7653 } EnvelopeData; 7654 7655 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7656 { 7657 EnvelopeData *edata = (EnvelopeData *)*ptr; 7658 7659 PetscFunctionBegin; 7660 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7661 PetscCall(PetscFree(edata->is)); 7662 PetscCall(PetscFree(edata)); 7663 PetscFunctionReturn(PETSC_SUCCESS); 7664 } 7665 7666 /*@ 7667 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7668 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7669 7670 Collective 7671 7672 Input Parameter: 7673 . mat - the matrix 7674 7675 Level: intermediate 7676 7677 Notes: 7678 There can be zeros within the blocks 7679 7680 The blocks can overlap between processes, including laying on more than two processes 7681 7682 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7683 @*/ 7684 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7685 { 7686 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7687 PetscInt *diag, *odiag, sc; 7688 VecScatter scatter; 7689 PetscScalar *seqv; 7690 const PetscScalar *parv; 7691 const PetscInt *ia, *ja; 7692 PetscBool set, flag, done; 7693 Mat AA = mat, A; 7694 MPI_Comm comm; 7695 PetscMPIInt rank, size, tag; 7696 MPI_Status status; 7697 PetscContainer container; 7698 EnvelopeData *edata; 7699 Vec seq, par; 7700 IS isglobal; 7701 7702 PetscFunctionBegin; 7703 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7704 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7705 if (!set || !flag) { 7706 /* TODO: only needs nonzero structure of transpose */ 7707 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7708 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7709 } 7710 PetscCall(MatAIJGetLocalMat(AA, &A)); 7711 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7712 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7713 7714 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7715 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7716 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7717 PetscCallMPI(MPI_Comm_size(comm, &size)); 7718 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7719 7720 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7721 7722 if (rank > 0) { 7723 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7724 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7725 } 7726 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7727 for (i = 0; i < n; i++) { 7728 env = PetscMax(env, ja[ia[i + 1] - 1]); 7729 II = rstart + i; 7730 if (env == II) { 7731 starts[lblocks] = tbs; 7732 sizes[lblocks++] = 1 + II - tbs; 7733 tbs = 1 + II; 7734 } 7735 } 7736 if (rank < size - 1) { 7737 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7738 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7739 } 7740 7741 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7742 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7743 PetscCall(MatDestroy(&A)); 7744 7745 PetscCall(PetscNew(&edata)); 7746 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7747 edata->n = lblocks; 7748 /* create IS needed for extracting blocks from the original matrix */ 7749 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7750 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7751 7752 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7753 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7754 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7755 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7756 PetscCall(MatSetType(edata->C, MATAIJ)); 7757 7758 /* Communicate the start and end of each row, from each block to the correct rank */ 7759 /* TODO: Use PetscSF instead of VecScatter */ 7760 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7761 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7762 PetscCall(VecGetArrayWrite(seq, &seqv)); 7763 for (PetscInt i = 0; i < lblocks; i++) { 7764 for (PetscInt j = 0; j < sizes[i]; j++) { 7765 seqv[cnt] = starts[i]; 7766 seqv[cnt + 1] = starts[i] + sizes[i]; 7767 cnt += 2; 7768 } 7769 } 7770 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7771 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7772 sc -= cnt; 7773 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7774 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7775 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7776 PetscCall(ISDestroy(&isglobal)); 7777 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7778 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7779 PetscCall(VecScatterDestroy(&scatter)); 7780 PetscCall(VecDestroy(&seq)); 7781 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7782 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7783 PetscCall(VecGetArrayRead(par, &parv)); 7784 cnt = 0; 7785 PetscCall(MatGetSize(mat, NULL, &n)); 7786 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7787 PetscInt start, end, d = 0, od = 0; 7788 7789 start = (PetscInt)PetscRealPart(parv[cnt]); 7790 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7791 cnt += 2; 7792 7793 if (start < cstart) { 7794 od += cstart - start + n - cend; 7795 d += cend - cstart; 7796 } else if (start < cend) { 7797 od += n - cend; 7798 d += cend - start; 7799 } else od += n - start; 7800 if (end <= cstart) { 7801 od -= cstart - end + n - cend; 7802 d -= cend - cstart; 7803 } else if (end < cend) { 7804 od -= n - cend; 7805 d -= cend - end; 7806 } else od -= n - end; 7807 7808 odiag[i] = od; 7809 diag[i] = d; 7810 } 7811 PetscCall(VecRestoreArrayRead(par, &parv)); 7812 PetscCall(VecDestroy(&par)); 7813 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7814 PetscCall(PetscFree2(diag, odiag)); 7815 PetscCall(PetscFree2(sizes, starts)); 7816 7817 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7818 PetscCall(PetscContainerSetPointer(container, edata)); 7819 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7820 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7821 PetscCall(PetscObjectDereference((PetscObject)container)); 7822 PetscFunctionReturn(PETSC_SUCCESS); 7823 } 7824 7825 /*@ 7826 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7827 7828 Collective 7829 7830 Input Parameters: 7831 + A - the matrix 7832 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7833 7834 Output Parameter: 7835 . C - matrix with inverted block diagonal of `A` 7836 7837 Level: advanced 7838 7839 Note: 7840 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7841 7842 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7843 @*/ 7844 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7845 { 7846 PetscContainer container; 7847 EnvelopeData *edata; 7848 PetscObjectState nonzerostate; 7849 7850 PetscFunctionBegin; 7851 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7852 if (!container) { 7853 PetscCall(MatComputeVariableBlockEnvelope(A)); 7854 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7855 } 7856 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7857 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7858 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7859 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7860 7861 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7862 *C = edata->C; 7863 7864 for (PetscInt i = 0; i < edata->n; i++) { 7865 Mat D; 7866 PetscScalar *dvalues; 7867 7868 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7869 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7870 PetscCall(MatSeqDenseInvert(D)); 7871 PetscCall(MatDenseGetArray(D, &dvalues)); 7872 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7873 PetscCall(MatDestroy(&D)); 7874 } 7875 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7876 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7877 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7878 PetscFunctionReturn(PETSC_SUCCESS); 7879 } 7880 7881 /*@ 7882 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7883 7884 Not Collective 7885 7886 Input Parameters: 7887 + mat - the matrix 7888 . nblocks - the number of blocks on this process, each block can only exist on a single process 7889 - bsizes - the block sizes 7890 7891 Level: intermediate 7892 7893 Notes: 7894 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7895 7896 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. 7897 7898 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7899 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7900 @*/ 7901 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7902 { 7903 PetscInt ncnt = 0, nlocal; 7904 7905 PetscFunctionBegin; 7906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7907 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7908 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); 7909 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7910 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); 7911 PetscCall(PetscFree(mat->bsizes)); 7912 mat->nblocks = nblocks; 7913 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7914 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7915 PetscFunctionReturn(PETSC_SUCCESS); 7916 } 7917 7918 /*@C 7919 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7920 7921 Not Collective; No Fortran Support 7922 7923 Input Parameter: 7924 . mat - the matrix 7925 7926 Output Parameters: 7927 + nblocks - the number of blocks on this process 7928 - bsizes - the block sizes 7929 7930 Level: intermediate 7931 7932 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7933 @*/ 7934 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7935 { 7936 PetscFunctionBegin; 7937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7938 if (nblocks) *nblocks = mat->nblocks; 7939 if (bsizes) *bsizes = mat->bsizes; 7940 PetscFunctionReturn(PETSC_SUCCESS); 7941 } 7942 7943 /*@ 7944 MatSetBlockSizes - Sets the matrix block row and column sizes. 7945 7946 Logically Collective 7947 7948 Input Parameters: 7949 + mat - the matrix 7950 . rbs - row block size 7951 - cbs - column block size 7952 7953 Level: intermediate 7954 7955 Notes: 7956 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7957 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7958 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7959 7960 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7961 are compatible with the matrix local sizes. 7962 7963 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7964 7965 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7966 @*/ 7967 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7968 { 7969 PetscFunctionBegin; 7970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7971 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7972 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7973 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7974 if (mat->rmap->refcnt) { 7975 ISLocalToGlobalMapping l2g = NULL; 7976 PetscLayout nmap = NULL; 7977 7978 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7979 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7980 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7981 mat->rmap = nmap; 7982 mat->rmap->mapping = l2g; 7983 } 7984 if (mat->cmap->refcnt) { 7985 ISLocalToGlobalMapping l2g = NULL; 7986 PetscLayout nmap = NULL; 7987 7988 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7989 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7990 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7991 mat->cmap = nmap; 7992 mat->cmap->mapping = l2g; 7993 } 7994 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7995 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7996 PetscFunctionReturn(PETSC_SUCCESS); 7997 } 7998 7999 /*@ 8000 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8001 8002 Logically Collective 8003 8004 Input Parameters: 8005 + mat - the matrix 8006 . fromRow - matrix from which to copy row block size 8007 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8008 8009 Level: developer 8010 8011 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8012 @*/ 8013 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8014 { 8015 PetscFunctionBegin; 8016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8017 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8018 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8019 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8020 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8021 PetscFunctionReturn(PETSC_SUCCESS); 8022 } 8023 8024 /*@ 8025 MatResidual - Default routine to calculate the residual r = b - Ax 8026 8027 Collective 8028 8029 Input Parameters: 8030 + mat - the matrix 8031 . b - the right-hand-side 8032 - x - the approximate solution 8033 8034 Output Parameter: 8035 . r - location to store the residual 8036 8037 Level: developer 8038 8039 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8040 @*/ 8041 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8042 { 8043 PetscFunctionBegin; 8044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8045 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8046 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8047 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8048 PetscValidType(mat, 1); 8049 MatCheckPreallocated(mat, 1); 8050 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8051 if (!mat->ops->residual) { 8052 PetscCall(MatMult(mat, x, r)); 8053 PetscCall(VecAYPX(r, -1.0, b)); 8054 } else { 8055 PetscUseTypeMethod(mat, residual, b, x, r); 8056 } 8057 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8058 PetscFunctionReturn(PETSC_SUCCESS); 8059 } 8060 8061 /*@C 8062 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8063 8064 Collective 8065 8066 Input Parameters: 8067 + mat - the matrix 8068 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8069 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8070 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8071 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8072 always used. 8073 8074 Output Parameters: 8075 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8076 . 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 8077 . ja - the column indices, use `NULL` if not needed 8078 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8079 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8080 8081 Level: developer 8082 8083 Notes: 8084 You CANNOT change any of the ia[] or ja[] values. 8085 8086 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8087 8088 Fortran Notes: 8089 Use 8090 .vb 8091 PetscInt, pointer :: ia(:),ja(:) 8092 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8093 ! Access the ith and jth entries via ia(i) and ja(j) 8094 .ve 8095 8096 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8097 @*/ 8098 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8099 { 8100 PetscFunctionBegin; 8101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8102 PetscValidType(mat, 1); 8103 if (n) PetscAssertPointer(n, 5); 8104 if (ia) PetscAssertPointer(ia, 6); 8105 if (ja) PetscAssertPointer(ja, 7); 8106 if (done) PetscAssertPointer(done, 8); 8107 MatCheckPreallocated(mat, 1); 8108 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8109 else { 8110 if (done) *done = PETSC_TRUE; 8111 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8112 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8113 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8114 } 8115 PetscFunctionReturn(PETSC_SUCCESS); 8116 } 8117 8118 /*@C 8119 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8120 8121 Collective 8122 8123 Input Parameters: 8124 + mat - the matrix 8125 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8126 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8127 symmetrized 8128 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8129 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8130 always used. 8131 . n - number of columns in the (possibly compressed) matrix 8132 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8133 - ja - the row indices 8134 8135 Output Parameter: 8136 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8137 8138 Level: developer 8139 8140 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8141 @*/ 8142 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8143 { 8144 PetscFunctionBegin; 8145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8146 PetscValidType(mat, 1); 8147 PetscAssertPointer(n, 5); 8148 if (ia) PetscAssertPointer(ia, 6); 8149 if (ja) PetscAssertPointer(ja, 7); 8150 PetscAssertPointer(done, 8); 8151 MatCheckPreallocated(mat, 1); 8152 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8153 else { 8154 *done = PETSC_TRUE; 8155 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8156 } 8157 PetscFunctionReturn(PETSC_SUCCESS); 8158 } 8159 8160 /*@C 8161 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8162 8163 Collective 8164 8165 Input Parameters: 8166 + mat - the matrix 8167 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8168 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8169 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8170 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8171 always used. 8172 . n - size of (possibly compressed) matrix 8173 . ia - the row pointers 8174 - ja - the column indices 8175 8176 Output Parameter: 8177 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8178 8179 Level: developer 8180 8181 Note: 8182 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8183 us of the array after it has been restored. If you pass `NULL`, it will 8184 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8185 8186 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8187 @*/ 8188 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8189 { 8190 PetscFunctionBegin; 8191 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8192 PetscValidType(mat, 1); 8193 if (ia) PetscAssertPointer(ia, 6); 8194 if (ja) PetscAssertPointer(ja, 7); 8195 if (done) PetscAssertPointer(done, 8); 8196 MatCheckPreallocated(mat, 1); 8197 8198 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8199 else { 8200 if (done) *done = PETSC_TRUE; 8201 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8202 if (n) *n = 0; 8203 if (ia) *ia = NULL; 8204 if (ja) *ja = NULL; 8205 } 8206 PetscFunctionReturn(PETSC_SUCCESS); 8207 } 8208 8209 /*@C 8210 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8211 8212 Collective 8213 8214 Input Parameters: 8215 + mat - the matrix 8216 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8217 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8218 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8219 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8220 always used. 8221 8222 Output Parameters: 8223 + n - size of (possibly compressed) matrix 8224 . ia - the column pointers 8225 . ja - the row indices 8226 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8227 8228 Level: developer 8229 8230 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8231 @*/ 8232 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8233 { 8234 PetscFunctionBegin; 8235 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8236 PetscValidType(mat, 1); 8237 if (ia) PetscAssertPointer(ia, 6); 8238 if (ja) PetscAssertPointer(ja, 7); 8239 PetscAssertPointer(done, 8); 8240 MatCheckPreallocated(mat, 1); 8241 8242 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8243 else { 8244 *done = PETSC_TRUE; 8245 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8246 if (n) *n = 0; 8247 if (ia) *ia = NULL; 8248 if (ja) *ja = NULL; 8249 } 8250 PetscFunctionReturn(PETSC_SUCCESS); 8251 } 8252 8253 /*@ 8254 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8255 `MatGetColumnIJ()`. 8256 8257 Collective 8258 8259 Input Parameters: 8260 + mat - the matrix 8261 . ncolors - maximum color value 8262 . n - number of entries in colorarray 8263 - colorarray - array indicating color for each column 8264 8265 Output Parameter: 8266 . iscoloring - coloring generated using colorarray information 8267 8268 Level: developer 8269 8270 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8271 @*/ 8272 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8273 { 8274 PetscFunctionBegin; 8275 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8276 PetscValidType(mat, 1); 8277 PetscAssertPointer(colorarray, 4); 8278 PetscAssertPointer(iscoloring, 5); 8279 MatCheckPreallocated(mat, 1); 8280 8281 if (!mat->ops->coloringpatch) { 8282 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8283 } else { 8284 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8285 } 8286 PetscFunctionReturn(PETSC_SUCCESS); 8287 } 8288 8289 /*@ 8290 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8291 8292 Logically Collective 8293 8294 Input Parameter: 8295 . mat - the factored matrix to be reset 8296 8297 Level: developer 8298 8299 Notes: 8300 This routine should be used only with factored matrices formed by in-place 8301 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8302 format). This option can save memory, for example, when solving nonlinear 8303 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8304 ILU(0) preconditioner. 8305 8306 One can specify in-place ILU(0) factorization by calling 8307 .vb 8308 PCType(pc,PCILU); 8309 PCFactorSeUseInPlace(pc); 8310 .ve 8311 or by using the options -pc_type ilu -pc_factor_in_place 8312 8313 In-place factorization ILU(0) can also be used as a local 8314 solver for the blocks within the block Jacobi or additive Schwarz 8315 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8316 for details on setting local solver options. 8317 8318 Most users should employ the `KSP` interface for linear solvers 8319 instead of working directly with matrix algebra routines such as this. 8320 See, e.g., `KSPCreate()`. 8321 8322 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8323 @*/ 8324 PetscErrorCode MatSetUnfactored(Mat mat) 8325 { 8326 PetscFunctionBegin; 8327 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8328 PetscValidType(mat, 1); 8329 MatCheckPreallocated(mat, 1); 8330 mat->factortype = MAT_FACTOR_NONE; 8331 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8332 PetscUseTypeMethod(mat, setunfactored); 8333 PetscFunctionReturn(PETSC_SUCCESS); 8334 } 8335 8336 /*@ 8337 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8338 as the original matrix. 8339 8340 Collective 8341 8342 Input Parameters: 8343 + mat - the original matrix 8344 . isrow - parallel `IS` containing the rows this processor should obtain 8345 . 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. 8346 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8347 8348 Output Parameter: 8349 . newmat - the new submatrix, of the same type as the original matrix 8350 8351 Level: advanced 8352 8353 Notes: 8354 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8355 8356 Some matrix types place restrictions on the row and column indices, such 8357 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; 8358 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8359 8360 The index sets may not have duplicate entries. 8361 8362 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8363 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8364 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8365 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8366 you are finished using it. 8367 8368 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8369 the input matrix. 8370 8371 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8372 8373 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8374 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8375 8376 Example usage: 8377 Consider the following 8x8 matrix with 34 non-zero values, that is 8378 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8379 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8380 as follows 8381 .vb 8382 1 2 0 | 0 3 0 | 0 4 8383 Proc0 0 5 6 | 7 0 0 | 8 0 8384 9 0 10 | 11 0 0 | 12 0 8385 ------------------------------------- 8386 13 0 14 | 15 16 17 | 0 0 8387 Proc1 0 18 0 | 19 20 21 | 0 0 8388 0 0 0 | 22 23 0 | 24 0 8389 ------------------------------------- 8390 Proc2 25 26 27 | 0 0 28 | 29 0 8391 30 0 0 | 31 32 33 | 0 34 8392 .ve 8393 8394 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8395 8396 .vb 8397 2 0 | 0 3 0 | 0 8398 Proc0 5 6 | 7 0 0 | 8 8399 ------------------------------- 8400 Proc1 18 0 | 19 20 21 | 0 8401 ------------------------------- 8402 Proc2 26 27 | 0 0 28 | 29 8403 0 0 | 31 32 33 | 0 8404 .ve 8405 8406 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8407 @*/ 8408 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8409 { 8410 PetscMPIInt size; 8411 Mat *local; 8412 IS iscoltmp; 8413 PetscBool flg; 8414 8415 PetscFunctionBegin; 8416 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8417 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8418 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8419 PetscAssertPointer(newmat, 5); 8420 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8421 PetscValidType(mat, 1); 8422 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8423 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8424 8425 MatCheckPreallocated(mat, 1); 8426 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8427 8428 if (!iscol || isrow == iscol) { 8429 PetscBool stride; 8430 PetscMPIInt grabentirematrix = 0, grab; 8431 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8432 if (stride) { 8433 PetscInt first, step, n, rstart, rend; 8434 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8435 if (step == 1) { 8436 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8437 if (rstart == first) { 8438 PetscCall(ISGetLocalSize(isrow, &n)); 8439 if (n == rend - rstart) grabentirematrix = 1; 8440 } 8441 } 8442 } 8443 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8444 if (grab) { 8445 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8446 if (cll == MAT_INITIAL_MATRIX) { 8447 *newmat = mat; 8448 PetscCall(PetscObjectReference((PetscObject)mat)); 8449 } 8450 PetscFunctionReturn(PETSC_SUCCESS); 8451 } 8452 } 8453 8454 if (!iscol) { 8455 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8456 } else { 8457 iscoltmp = iscol; 8458 } 8459 8460 /* if original matrix is on just one processor then use submatrix generated */ 8461 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8462 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8463 goto setproperties; 8464 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8465 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8466 *newmat = *local; 8467 PetscCall(PetscFree(local)); 8468 goto setproperties; 8469 } else if (!mat->ops->createsubmatrix) { 8470 /* Create a new matrix type that implements the operation using the full matrix */ 8471 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8472 switch (cll) { 8473 case MAT_INITIAL_MATRIX: 8474 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8475 break; 8476 case MAT_REUSE_MATRIX: 8477 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8478 break; 8479 default: 8480 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8481 } 8482 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8483 goto setproperties; 8484 } 8485 8486 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8487 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8488 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8489 8490 setproperties: 8491 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8492 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8493 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8494 } 8495 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8496 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8497 PetscFunctionReturn(PETSC_SUCCESS); 8498 } 8499 8500 /*@ 8501 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8502 8503 Not Collective 8504 8505 Input Parameters: 8506 + A - the matrix we wish to propagate options from 8507 - B - the matrix we wish to propagate options to 8508 8509 Level: beginner 8510 8511 Note: 8512 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8513 8514 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8515 @*/ 8516 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8517 { 8518 PetscFunctionBegin; 8519 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8520 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8521 B->symmetry_eternal = A->symmetry_eternal; 8522 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8523 B->symmetric = A->symmetric; 8524 B->structurally_symmetric = A->structurally_symmetric; 8525 B->spd = A->spd; 8526 B->hermitian = A->hermitian; 8527 PetscFunctionReturn(PETSC_SUCCESS); 8528 } 8529 8530 /*@ 8531 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8532 used during the assembly process to store values that belong to 8533 other processors. 8534 8535 Not Collective 8536 8537 Input Parameters: 8538 + mat - the matrix 8539 . size - the initial size of the stash. 8540 - bsize - the initial size of the block-stash(if used). 8541 8542 Options Database Keys: 8543 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8544 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8545 8546 Level: intermediate 8547 8548 Notes: 8549 The block-stash is used for values set with `MatSetValuesBlocked()` while 8550 the stash is used for values set with `MatSetValues()` 8551 8552 Run with the option -info and look for output of the form 8553 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8554 to determine the appropriate value, MM, to use for size and 8555 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8556 to determine the value, BMM to use for bsize 8557 8558 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8559 @*/ 8560 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8561 { 8562 PetscFunctionBegin; 8563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8564 PetscValidType(mat, 1); 8565 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8566 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8567 PetscFunctionReturn(PETSC_SUCCESS); 8568 } 8569 8570 /*@ 8571 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8572 the matrix 8573 8574 Neighbor-wise Collective 8575 8576 Input Parameters: 8577 + A - the matrix 8578 . x - the vector to be multiplied by the interpolation operator 8579 - y - the vector to be added to the result 8580 8581 Output Parameter: 8582 . w - the resulting vector 8583 8584 Level: intermediate 8585 8586 Notes: 8587 `w` may be the same vector as `y`. 8588 8589 This allows one to use either the restriction or interpolation (its transpose) 8590 matrix to do the interpolation 8591 8592 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8593 @*/ 8594 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8595 { 8596 PetscInt M, N, Ny; 8597 8598 PetscFunctionBegin; 8599 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8600 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8601 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8602 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8603 PetscCall(MatGetSize(A, &M, &N)); 8604 PetscCall(VecGetSize(y, &Ny)); 8605 if (M == Ny) { 8606 PetscCall(MatMultAdd(A, x, y, w)); 8607 } else { 8608 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8609 } 8610 PetscFunctionReturn(PETSC_SUCCESS); 8611 } 8612 8613 /*@ 8614 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8615 the matrix 8616 8617 Neighbor-wise Collective 8618 8619 Input Parameters: 8620 + A - the matrix 8621 - x - the vector to be interpolated 8622 8623 Output Parameter: 8624 . y - the resulting vector 8625 8626 Level: intermediate 8627 8628 Note: 8629 This allows one to use either the restriction or interpolation (its transpose) 8630 matrix to do the interpolation 8631 8632 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8633 @*/ 8634 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8635 { 8636 PetscInt M, N, Ny; 8637 8638 PetscFunctionBegin; 8639 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8640 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8641 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8642 PetscCall(MatGetSize(A, &M, &N)); 8643 PetscCall(VecGetSize(y, &Ny)); 8644 if (M == Ny) { 8645 PetscCall(MatMult(A, x, y)); 8646 } else { 8647 PetscCall(MatMultTranspose(A, x, y)); 8648 } 8649 PetscFunctionReturn(PETSC_SUCCESS); 8650 } 8651 8652 /*@ 8653 MatRestrict - $y = A*x$ or $A^T*x$ 8654 8655 Neighbor-wise Collective 8656 8657 Input Parameters: 8658 + A - the matrix 8659 - x - the vector to be restricted 8660 8661 Output Parameter: 8662 . y - the resulting vector 8663 8664 Level: intermediate 8665 8666 Note: 8667 This allows one to use either the restriction or interpolation (its transpose) 8668 matrix to do the restriction 8669 8670 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8671 @*/ 8672 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8673 { 8674 PetscInt M, N, Nx; 8675 8676 PetscFunctionBegin; 8677 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8678 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8679 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8680 PetscCall(MatGetSize(A, &M, &N)); 8681 PetscCall(VecGetSize(x, &Nx)); 8682 if (M == Nx) { 8683 PetscCall(MatMultTranspose(A, x, y)); 8684 } else { 8685 PetscCall(MatMult(A, x, y)); 8686 } 8687 PetscFunctionReturn(PETSC_SUCCESS); 8688 } 8689 8690 /*@ 8691 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8692 8693 Neighbor-wise Collective 8694 8695 Input Parameters: 8696 + A - the matrix 8697 . x - the input dense matrix to be multiplied 8698 - w - the input dense matrix to be added to the result 8699 8700 Output Parameter: 8701 . y - the output dense matrix 8702 8703 Level: intermediate 8704 8705 Note: 8706 This allows one to use either the restriction or interpolation (its transpose) 8707 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8708 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8709 8710 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8711 @*/ 8712 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8713 { 8714 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8715 PetscBool trans = PETSC_TRUE; 8716 MatReuse reuse = MAT_INITIAL_MATRIX; 8717 8718 PetscFunctionBegin; 8719 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8720 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8721 PetscValidType(x, 2); 8722 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8723 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8724 PetscCall(MatGetSize(A, &M, &N)); 8725 PetscCall(MatGetSize(x, &Mx, &Nx)); 8726 if (N == Mx) trans = PETSC_FALSE; 8727 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); 8728 Mo = trans ? N : M; 8729 if (*y) { 8730 PetscCall(MatGetSize(*y, &My, &Ny)); 8731 if (Mo == My && Nx == Ny) { 8732 reuse = MAT_REUSE_MATRIX; 8733 } else { 8734 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); 8735 PetscCall(MatDestroy(y)); 8736 } 8737 } 8738 8739 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8740 PetscBool flg; 8741 8742 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8743 if (w) { 8744 PetscInt My, Ny, Mw, Nw; 8745 8746 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8747 PetscCall(MatGetSize(*y, &My, &Ny)); 8748 PetscCall(MatGetSize(w, &Mw, &Nw)); 8749 if (!flg || My != Mw || Ny != Nw) w = NULL; 8750 } 8751 if (!w) { 8752 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8753 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8754 PetscCall(PetscObjectDereference((PetscObject)w)); 8755 } else { 8756 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8757 } 8758 } 8759 if (!trans) { 8760 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8761 } else { 8762 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8763 } 8764 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8765 PetscFunctionReturn(PETSC_SUCCESS); 8766 } 8767 8768 /*@ 8769 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8770 8771 Neighbor-wise Collective 8772 8773 Input Parameters: 8774 + A - the matrix 8775 - x - the input dense matrix 8776 8777 Output Parameter: 8778 . y - the output dense matrix 8779 8780 Level: intermediate 8781 8782 Note: 8783 This allows one to use either the restriction or interpolation (its transpose) 8784 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8785 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8786 8787 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8788 @*/ 8789 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8790 { 8791 PetscFunctionBegin; 8792 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8793 PetscFunctionReturn(PETSC_SUCCESS); 8794 } 8795 8796 /*@ 8797 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8798 8799 Neighbor-wise Collective 8800 8801 Input Parameters: 8802 + A - the matrix 8803 - x - the input dense matrix 8804 8805 Output Parameter: 8806 . y - the output dense matrix 8807 8808 Level: intermediate 8809 8810 Note: 8811 This allows one to use either the restriction or interpolation (its transpose) 8812 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8813 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8814 8815 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8816 @*/ 8817 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8818 { 8819 PetscFunctionBegin; 8820 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8821 PetscFunctionReturn(PETSC_SUCCESS); 8822 } 8823 8824 /*@ 8825 MatGetNullSpace - retrieves the null space of a matrix. 8826 8827 Logically Collective 8828 8829 Input Parameters: 8830 + mat - the matrix 8831 - nullsp - the null space object 8832 8833 Level: developer 8834 8835 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8836 @*/ 8837 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8838 { 8839 PetscFunctionBegin; 8840 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8841 PetscAssertPointer(nullsp, 2); 8842 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8843 PetscFunctionReturn(PETSC_SUCCESS); 8844 } 8845 8846 /*@C 8847 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8848 8849 Logically Collective 8850 8851 Input Parameters: 8852 + n - the number of matrices 8853 - mat - the array of matrices 8854 8855 Output Parameters: 8856 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8857 8858 Level: developer 8859 8860 Note: 8861 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8862 8863 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8864 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8865 @*/ 8866 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8867 { 8868 PetscFunctionBegin; 8869 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8870 PetscAssertPointer(mat, 2); 8871 PetscAssertPointer(nullsp, 3); 8872 8873 PetscCall(PetscCalloc1(3 * n, nullsp)); 8874 for (PetscInt i = 0; i < n; i++) { 8875 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8876 (*nullsp)[i] = mat[i]->nullsp; 8877 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8878 (*nullsp)[n + i] = mat[i]->nearnullsp; 8879 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8880 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8881 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8882 } 8883 PetscFunctionReturn(PETSC_SUCCESS); 8884 } 8885 8886 /*@C 8887 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8888 8889 Logically Collective 8890 8891 Input Parameters: 8892 + n - the number of matrices 8893 . mat - the array of matrices 8894 - nullsp - an array of null spaces 8895 8896 Level: developer 8897 8898 Note: 8899 Call `MatGetNullSpaces()` to create `nullsp` 8900 8901 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8902 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8903 @*/ 8904 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8905 { 8906 PetscFunctionBegin; 8907 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8908 PetscAssertPointer(mat, 2); 8909 PetscAssertPointer(nullsp, 3); 8910 PetscAssertPointer(*nullsp, 3); 8911 8912 for (PetscInt i = 0; i < n; i++) { 8913 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8914 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8915 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8916 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8917 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8918 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8919 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8920 } 8921 PetscCall(PetscFree(*nullsp)); 8922 PetscFunctionReturn(PETSC_SUCCESS); 8923 } 8924 8925 /*@ 8926 MatSetNullSpace - attaches a null space to a matrix. 8927 8928 Logically Collective 8929 8930 Input Parameters: 8931 + mat - the matrix 8932 - nullsp - the null space object 8933 8934 Level: advanced 8935 8936 Notes: 8937 This null space is used by the `KSP` linear solvers to solve singular systems. 8938 8939 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` 8940 8941 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 8942 to zero but the linear system will still be solved in a least squares sense. 8943 8944 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8945 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)$. 8946 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 8947 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 8948 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$). 8949 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8950 8951 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8952 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8953 routine also automatically calls `MatSetTransposeNullSpace()`. 8954 8955 The user should call `MatNullSpaceDestroy()`. 8956 8957 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8958 `KSPSetPCSide()` 8959 @*/ 8960 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8961 { 8962 PetscFunctionBegin; 8963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8964 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8965 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8966 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8967 mat->nullsp = nullsp; 8968 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8969 PetscFunctionReturn(PETSC_SUCCESS); 8970 } 8971 8972 /*@ 8973 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8974 8975 Logically Collective 8976 8977 Input Parameters: 8978 + mat - the matrix 8979 - nullsp - the null space object 8980 8981 Level: developer 8982 8983 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8984 @*/ 8985 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8986 { 8987 PetscFunctionBegin; 8988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8989 PetscValidType(mat, 1); 8990 PetscAssertPointer(nullsp, 2); 8991 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8992 PetscFunctionReturn(PETSC_SUCCESS); 8993 } 8994 8995 /*@ 8996 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8997 8998 Logically Collective 8999 9000 Input Parameters: 9001 + mat - the matrix 9002 - nullsp - the null space object 9003 9004 Level: advanced 9005 9006 Notes: 9007 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9008 9009 See `MatSetNullSpace()` 9010 9011 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9012 @*/ 9013 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9014 { 9015 PetscFunctionBegin; 9016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9017 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9018 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9019 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9020 mat->transnullsp = nullsp; 9021 PetscFunctionReturn(PETSC_SUCCESS); 9022 } 9023 9024 /*@ 9025 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9026 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9027 9028 Logically Collective 9029 9030 Input Parameters: 9031 + mat - the matrix 9032 - nullsp - the null space object 9033 9034 Level: advanced 9035 9036 Notes: 9037 Overwrites any previous near null space that may have been attached 9038 9039 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9040 9041 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9042 @*/ 9043 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9044 { 9045 PetscFunctionBegin; 9046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9047 PetscValidType(mat, 1); 9048 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9049 MatCheckPreallocated(mat, 1); 9050 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9051 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9052 mat->nearnullsp = nullsp; 9053 PetscFunctionReturn(PETSC_SUCCESS); 9054 } 9055 9056 /*@ 9057 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9058 9059 Not Collective 9060 9061 Input Parameter: 9062 . mat - the matrix 9063 9064 Output Parameter: 9065 . nullsp - the null space object, `NULL` if not set 9066 9067 Level: advanced 9068 9069 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9070 @*/ 9071 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9072 { 9073 PetscFunctionBegin; 9074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9075 PetscValidType(mat, 1); 9076 PetscAssertPointer(nullsp, 2); 9077 MatCheckPreallocated(mat, 1); 9078 *nullsp = mat->nearnullsp; 9079 PetscFunctionReturn(PETSC_SUCCESS); 9080 } 9081 9082 /*@ 9083 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9084 9085 Collective 9086 9087 Input Parameters: 9088 + mat - the matrix 9089 . row - row/column permutation 9090 - info - information on desired factorization process 9091 9092 Level: developer 9093 9094 Notes: 9095 Probably really in-place only when level of fill is zero, otherwise allocates 9096 new space to store factored matrix and deletes previous memory. 9097 9098 Most users should employ the `KSP` interface for linear solvers 9099 instead of working directly with matrix algebra routines such as this. 9100 See, e.g., `KSPCreate()`. 9101 9102 Developer Note: 9103 The Fortran interface is not autogenerated as the 9104 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9105 9106 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9107 @*/ 9108 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9109 { 9110 PetscFunctionBegin; 9111 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9112 PetscValidType(mat, 1); 9113 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9114 PetscAssertPointer(info, 3); 9115 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9116 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9117 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9118 MatCheckPreallocated(mat, 1); 9119 PetscUseTypeMethod(mat, iccfactor, row, info); 9120 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9121 PetscFunctionReturn(PETSC_SUCCESS); 9122 } 9123 9124 /*@ 9125 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9126 ghosted ones. 9127 9128 Not Collective 9129 9130 Input Parameters: 9131 + mat - the matrix 9132 - diag - the diagonal values, including ghost ones 9133 9134 Level: developer 9135 9136 Notes: 9137 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9138 9139 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9140 9141 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9142 @*/ 9143 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9144 { 9145 PetscMPIInt size; 9146 9147 PetscFunctionBegin; 9148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9149 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9150 PetscValidType(mat, 1); 9151 9152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9153 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9154 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9155 if (size == 1) { 9156 PetscInt n, m; 9157 PetscCall(VecGetSize(diag, &n)); 9158 PetscCall(MatGetSize(mat, NULL, &m)); 9159 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9160 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9161 } else { 9162 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9163 } 9164 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9165 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9166 PetscFunctionReturn(PETSC_SUCCESS); 9167 } 9168 9169 /*@ 9170 MatGetInertia - Gets the inertia from a factored matrix 9171 9172 Collective 9173 9174 Input Parameter: 9175 . mat - the matrix 9176 9177 Output Parameters: 9178 + nneg - number of negative eigenvalues 9179 . nzero - number of zero eigenvalues 9180 - npos - number of positive eigenvalues 9181 9182 Level: advanced 9183 9184 Note: 9185 Matrix must have been factored by `MatCholeskyFactor()` 9186 9187 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9188 @*/ 9189 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9190 { 9191 PetscFunctionBegin; 9192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9193 PetscValidType(mat, 1); 9194 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9195 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9196 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9197 PetscFunctionReturn(PETSC_SUCCESS); 9198 } 9199 9200 /*@C 9201 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9202 9203 Neighbor-wise Collective 9204 9205 Input Parameters: 9206 + mat - the factored matrix obtained with `MatGetFactor()` 9207 - b - the right-hand-side vectors 9208 9209 Output Parameter: 9210 . x - the result vectors 9211 9212 Level: developer 9213 9214 Note: 9215 The vectors `b` and `x` cannot be the same. I.e., one cannot 9216 call `MatSolves`(A,x,x). 9217 9218 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9219 @*/ 9220 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9221 { 9222 PetscFunctionBegin; 9223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9224 PetscValidType(mat, 1); 9225 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9226 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9227 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9228 9229 MatCheckPreallocated(mat, 1); 9230 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9231 PetscUseTypeMethod(mat, solves, b, x); 9232 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9233 PetscFunctionReturn(PETSC_SUCCESS); 9234 } 9235 9236 /*@ 9237 MatIsSymmetric - Test whether a matrix is symmetric 9238 9239 Collective 9240 9241 Input Parameters: 9242 + A - the matrix to test 9243 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9244 9245 Output Parameter: 9246 . flg - the result 9247 9248 Level: intermediate 9249 9250 Notes: 9251 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9252 9253 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9254 9255 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9256 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9257 9258 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9259 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9260 @*/ 9261 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9262 { 9263 PetscFunctionBegin; 9264 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9265 PetscAssertPointer(flg, 3); 9266 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9267 else { 9268 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9269 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9270 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9271 } 9272 PetscFunctionReturn(PETSC_SUCCESS); 9273 } 9274 9275 /*@ 9276 MatIsHermitian - Test whether a matrix is Hermitian 9277 9278 Collective 9279 9280 Input Parameters: 9281 + A - the matrix to test 9282 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9283 9284 Output Parameter: 9285 . flg - the result 9286 9287 Level: intermediate 9288 9289 Notes: 9290 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9291 9292 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9293 9294 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9295 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9296 9297 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9298 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9299 @*/ 9300 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9301 { 9302 PetscFunctionBegin; 9303 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9304 PetscAssertPointer(flg, 3); 9305 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9306 else { 9307 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9308 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9309 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9310 } 9311 PetscFunctionReturn(PETSC_SUCCESS); 9312 } 9313 9314 /*@ 9315 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9316 9317 Not Collective 9318 9319 Input Parameter: 9320 . A - the matrix to check 9321 9322 Output Parameters: 9323 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9324 - flg - the result (only valid if set is `PETSC_TRUE`) 9325 9326 Level: advanced 9327 9328 Notes: 9329 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9330 if you want it explicitly checked 9331 9332 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9333 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9334 9335 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9336 @*/ 9337 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9338 { 9339 PetscFunctionBegin; 9340 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9341 PetscAssertPointer(set, 2); 9342 PetscAssertPointer(flg, 3); 9343 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9344 *set = PETSC_TRUE; 9345 *flg = PetscBool3ToBool(A->symmetric); 9346 } else { 9347 *set = PETSC_FALSE; 9348 } 9349 PetscFunctionReturn(PETSC_SUCCESS); 9350 } 9351 9352 /*@ 9353 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9354 9355 Not Collective 9356 9357 Input Parameter: 9358 . A - the matrix to check 9359 9360 Output Parameters: 9361 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9362 - flg - the result (only valid if set is `PETSC_TRUE`) 9363 9364 Level: advanced 9365 9366 Notes: 9367 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9368 9369 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9370 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9371 9372 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9373 @*/ 9374 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9375 { 9376 PetscFunctionBegin; 9377 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9378 PetscAssertPointer(set, 2); 9379 PetscAssertPointer(flg, 3); 9380 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9381 *set = PETSC_TRUE; 9382 *flg = PetscBool3ToBool(A->spd); 9383 } else { 9384 *set = PETSC_FALSE; 9385 } 9386 PetscFunctionReturn(PETSC_SUCCESS); 9387 } 9388 9389 /*@ 9390 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9391 9392 Not Collective 9393 9394 Input Parameter: 9395 . A - the matrix to check 9396 9397 Output Parameters: 9398 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9399 - flg - the result (only valid if set is `PETSC_TRUE`) 9400 9401 Level: advanced 9402 9403 Notes: 9404 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9405 if you want it explicitly checked 9406 9407 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9408 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9409 9410 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9411 @*/ 9412 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9413 { 9414 PetscFunctionBegin; 9415 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9416 PetscAssertPointer(set, 2); 9417 PetscAssertPointer(flg, 3); 9418 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9419 *set = PETSC_TRUE; 9420 *flg = PetscBool3ToBool(A->hermitian); 9421 } else { 9422 *set = PETSC_FALSE; 9423 } 9424 PetscFunctionReturn(PETSC_SUCCESS); 9425 } 9426 9427 /*@ 9428 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9429 9430 Collective 9431 9432 Input Parameter: 9433 . A - the matrix to test 9434 9435 Output Parameter: 9436 . flg - the result 9437 9438 Level: intermediate 9439 9440 Notes: 9441 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9442 9443 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 9444 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9445 9446 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9447 @*/ 9448 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9449 { 9450 PetscFunctionBegin; 9451 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9452 PetscAssertPointer(flg, 2); 9453 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9454 *flg = PetscBool3ToBool(A->structurally_symmetric); 9455 } else { 9456 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9457 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9458 } 9459 PetscFunctionReturn(PETSC_SUCCESS); 9460 } 9461 9462 /*@ 9463 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9464 9465 Not Collective 9466 9467 Input Parameter: 9468 . A - the matrix to check 9469 9470 Output Parameters: 9471 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9472 - flg - the result (only valid if set is PETSC_TRUE) 9473 9474 Level: advanced 9475 9476 Notes: 9477 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 9478 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9479 9480 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9481 9482 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9483 @*/ 9484 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9485 { 9486 PetscFunctionBegin; 9487 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9488 PetscAssertPointer(set, 2); 9489 PetscAssertPointer(flg, 3); 9490 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9491 *set = PETSC_TRUE; 9492 *flg = PetscBool3ToBool(A->structurally_symmetric); 9493 } else { 9494 *set = PETSC_FALSE; 9495 } 9496 PetscFunctionReturn(PETSC_SUCCESS); 9497 } 9498 9499 /*@ 9500 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9501 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9502 9503 Not Collective 9504 9505 Input Parameter: 9506 . mat - the matrix 9507 9508 Output Parameters: 9509 + nstash - the size of the stash 9510 . reallocs - the number of additional mallocs incurred. 9511 . bnstash - the size of the block stash 9512 - breallocs - the number of additional mallocs incurred.in the block stash 9513 9514 Level: advanced 9515 9516 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9517 @*/ 9518 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9519 { 9520 PetscFunctionBegin; 9521 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9522 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9523 PetscFunctionReturn(PETSC_SUCCESS); 9524 } 9525 9526 /*@ 9527 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9528 parallel layout, `PetscLayout` for rows and columns 9529 9530 Collective 9531 9532 Input Parameter: 9533 . mat - the matrix 9534 9535 Output Parameters: 9536 + right - (optional) vector that the matrix can be multiplied against 9537 - left - (optional) vector that the matrix vector product can be stored in 9538 9539 Level: advanced 9540 9541 Notes: 9542 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()`. 9543 9544 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9545 9546 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9547 @*/ 9548 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9549 { 9550 PetscFunctionBegin; 9551 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9552 PetscValidType(mat, 1); 9553 if (mat->ops->getvecs) { 9554 PetscUseTypeMethod(mat, getvecs, right, left); 9555 } else { 9556 if (right) { 9557 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9558 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9559 PetscCall(VecSetType(*right, mat->defaultvectype)); 9560 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9561 if (mat->boundtocpu && mat->bindingpropagates) { 9562 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9563 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9564 } 9565 #endif 9566 } 9567 if (left) { 9568 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9569 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9570 PetscCall(VecSetType(*left, mat->defaultvectype)); 9571 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9572 if (mat->boundtocpu && mat->bindingpropagates) { 9573 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9574 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9575 } 9576 #endif 9577 } 9578 } 9579 PetscFunctionReturn(PETSC_SUCCESS); 9580 } 9581 9582 /*@ 9583 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9584 with default values. 9585 9586 Not Collective 9587 9588 Input Parameter: 9589 . info - the `MatFactorInfo` data structure 9590 9591 Level: developer 9592 9593 Notes: 9594 The solvers are generally used through the `KSP` and `PC` objects, for example 9595 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9596 9597 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9598 9599 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9600 @*/ 9601 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9602 { 9603 PetscFunctionBegin; 9604 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9605 PetscFunctionReturn(PETSC_SUCCESS); 9606 } 9607 9608 /*@ 9609 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9610 9611 Collective 9612 9613 Input Parameters: 9614 + mat - the factored matrix 9615 - is - the index set defining the Schur indices (0-based) 9616 9617 Level: advanced 9618 9619 Notes: 9620 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9621 9622 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9623 9624 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9625 9626 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9627 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9628 @*/ 9629 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9630 { 9631 PetscErrorCode (*f)(Mat, IS); 9632 9633 PetscFunctionBegin; 9634 PetscValidType(mat, 1); 9635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9636 PetscValidType(is, 2); 9637 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9638 PetscCheckSameComm(mat, 1, is, 2); 9639 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9640 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9641 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9642 PetscCall(MatDestroy(&mat->schur)); 9643 PetscCall((*f)(mat, is)); 9644 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9645 PetscFunctionReturn(PETSC_SUCCESS); 9646 } 9647 9648 /*@ 9649 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9650 9651 Logically Collective 9652 9653 Input Parameters: 9654 + F - the factored matrix obtained by calling `MatGetFactor()` 9655 . S - location where to return the Schur complement, can be `NULL` 9656 - status - the status of the Schur complement matrix, can be `NULL` 9657 9658 Level: advanced 9659 9660 Notes: 9661 You must call `MatFactorSetSchurIS()` before calling this routine. 9662 9663 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9664 9665 The routine provides a copy of the Schur matrix stored within the solver data structures. 9666 The caller must destroy the object when it is no longer needed. 9667 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9668 9669 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) 9670 9671 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9672 9673 Developer Note: 9674 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9675 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9676 9677 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9678 @*/ 9679 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9680 { 9681 PetscFunctionBegin; 9682 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9683 if (S) PetscAssertPointer(S, 2); 9684 if (status) PetscAssertPointer(status, 3); 9685 if (S) { 9686 PetscErrorCode (*f)(Mat, Mat *); 9687 9688 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9689 if (f) { 9690 PetscCall((*f)(F, S)); 9691 } else { 9692 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9693 } 9694 } 9695 if (status) *status = F->schur_status; 9696 PetscFunctionReturn(PETSC_SUCCESS); 9697 } 9698 9699 /*@ 9700 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9701 9702 Logically Collective 9703 9704 Input Parameters: 9705 + F - the factored matrix obtained by calling `MatGetFactor()` 9706 . S - location where to return the Schur complement, can be `NULL` 9707 - status - the status of the Schur complement matrix, can be `NULL` 9708 9709 Level: advanced 9710 9711 Notes: 9712 You must call `MatFactorSetSchurIS()` before calling this routine. 9713 9714 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9715 9716 The routine returns a the Schur Complement stored within the data structures of the solver. 9717 9718 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9719 9720 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9721 9722 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9723 9724 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9725 9726 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9727 @*/ 9728 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9729 { 9730 PetscFunctionBegin; 9731 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9732 if (S) { 9733 PetscAssertPointer(S, 2); 9734 *S = F->schur; 9735 } 9736 if (status) { 9737 PetscAssertPointer(status, 3); 9738 *status = F->schur_status; 9739 } 9740 PetscFunctionReturn(PETSC_SUCCESS); 9741 } 9742 9743 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9744 { 9745 Mat S = F->schur; 9746 9747 PetscFunctionBegin; 9748 switch (F->schur_status) { 9749 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9750 case MAT_FACTOR_SCHUR_INVERTED: 9751 if (S) { 9752 S->ops->solve = NULL; 9753 S->ops->matsolve = NULL; 9754 S->ops->solvetranspose = NULL; 9755 S->ops->matsolvetranspose = NULL; 9756 S->ops->solveadd = NULL; 9757 S->ops->solvetransposeadd = NULL; 9758 S->factortype = MAT_FACTOR_NONE; 9759 PetscCall(PetscFree(S->solvertype)); 9760 } 9761 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9762 break; 9763 default: 9764 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9765 } 9766 PetscFunctionReturn(PETSC_SUCCESS); 9767 } 9768 9769 /*@ 9770 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9771 9772 Logically Collective 9773 9774 Input Parameters: 9775 + F - the factored matrix obtained by calling `MatGetFactor()` 9776 . S - location where the Schur complement is stored 9777 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9778 9779 Level: advanced 9780 9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9782 @*/ 9783 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9784 { 9785 PetscFunctionBegin; 9786 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9787 if (S) { 9788 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9789 *S = NULL; 9790 } 9791 F->schur_status = status; 9792 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9793 PetscFunctionReturn(PETSC_SUCCESS); 9794 } 9795 9796 /*@ 9797 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9798 9799 Logically Collective 9800 9801 Input Parameters: 9802 + F - the factored matrix obtained by calling `MatGetFactor()` 9803 . rhs - location where the right-hand side of the Schur complement system is stored 9804 - sol - location where the solution of the Schur complement system has to be returned 9805 9806 Level: advanced 9807 9808 Notes: 9809 The sizes of the vectors should match the size of the Schur complement 9810 9811 Must be called after `MatFactorSetSchurIS()` 9812 9813 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9814 @*/ 9815 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9816 { 9817 PetscFunctionBegin; 9818 PetscValidType(F, 1); 9819 PetscValidType(rhs, 2); 9820 PetscValidType(sol, 3); 9821 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9822 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9823 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9824 PetscCheckSameComm(F, 1, rhs, 2); 9825 PetscCheckSameComm(F, 1, sol, 3); 9826 PetscCall(MatFactorFactorizeSchurComplement(F)); 9827 switch (F->schur_status) { 9828 case MAT_FACTOR_SCHUR_FACTORED: 9829 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9830 break; 9831 case MAT_FACTOR_SCHUR_INVERTED: 9832 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9833 break; 9834 default: 9835 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9836 } 9837 PetscFunctionReturn(PETSC_SUCCESS); 9838 } 9839 9840 /*@ 9841 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9842 9843 Logically Collective 9844 9845 Input Parameters: 9846 + F - the factored matrix obtained by calling `MatGetFactor()` 9847 . rhs - location where the right-hand side of the Schur complement system is stored 9848 - sol - location where the solution of the Schur complement system has to be returned 9849 9850 Level: advanced 9851 9852 Notes: 9853 The sizes of the vectors should match the size of the Schur complement 9854 9855 Must be called after `MatFactorSetSchurIS()` 9856 9857 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9858 @*/ 9859 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9860 { 9861 PetscFunctionBegin; 9862 PetscValidType(F, 1); 9863 PetscValidType(rhs, 2); 9864 PetscValidType(sol, 3); 9865 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9866 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9867 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9868 PetscCheckSameComm(F, 1, rhs, 2); 9869 PetscCheckSameComm(F, 1, sol, 3); 9870 PetscCall(MatFactorFactorizeSchurComplement(F)); 9871 switch (F->schur_status) { 9872 case MAT_FACTOR_SCHUR_FACTORED: 9873 PetscCall(MatSolve(F->schur, rhs, sol)); 9874 break; 9875 case MAT_FACTOR_SCHUR_INVERTED: 9876 PetscCall(MatMult(F->schur, rhs, sol)); 9877 break; 9878 default: 9879 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9880 } 9881 PetscFunctionReturn(PETSC_SUCCESS); 9882 } 9883 9884 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9885 #if PetscDefined(HAVE_CUDA) 9886 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9887 #endif 9888 9889 /* Schur status updated in the interface */ 9890 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9891 { 9892 Mat S = F->schur; 9893 9894 PetscFunctionBegin; 9895 if (S) { 9896 PetscMPIInt size; 9897 PetscBool isdense, isdensecuda; 9898 9899 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9900 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9901 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9902 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9903 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9904 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9905 if (isdense) { 9906 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9907 } else if (isdensecuda) { 9908 #if defined(PETSC_HAVE_CUDA) 9909 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9910 #endif 9911 } 9912 // HIP?????????????? 9913 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9914 } 9915 PetscFunctionReturn(PETSC_SUCCESS); 9916 } 9917 9918 /*@ 9919 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9920 9921 Logically Collective 9922 9923 Input Parameter: 9924 . F - the factored matrix obtained by calling `MatGetFactor()` 9925 9926 Level: advanced 9927 9928 Notes: 9929 Must be called after `MatFactorSetSchurIS()`. 9930 9931 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9932 9933 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9934 @*/ 9935 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9936 { 9937 PetscFunctionBegin; 9938 PetscValidType(F, 1); 9939 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9940 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9941 PetscCall(MatFactorFactorizeSchurComplement(F)); 9942 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9943 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9944 PetscFunctionReturn(PETSC_SUCCESS); 9945 } 9946 9947 /*@ 9948 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9949 9950 Logically Collective 9951 9952 Input Parameter: 9953 . F - the factored matrix obtained by calling `MatGetFactor()` 9954 9955 Level: advanced 9956 9957 Note: 9958 Must be called after `MatFactorSetSchurIS()` 9959 9960 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9961 @*/ 9962 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9963 { 9964 MatFactorInfo info; 9965 9966 PetscFunctionBegin; 9967 PetscValidType(F, 1); 9968 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9969 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9970 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9971 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9972 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9973 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9974 } else { 9975 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9976 } 9977 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9978 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9979 PetscFunctionReturn(PETSC_SUCCESS); 9980 } 9981 9982 /*@ 9983 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9984 9985 Neighbor-wise Collective 9986 9987 Input Parameters: 9988 + A - the matrix 9989 . P - the projection matrix 9990 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9991 - 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 9992 if the result is a dense matrix this is irrelevant 9993 9994 Output Parameter: 9995 . C - the product matrix 9996 9997 Level: intermediate 9998 9999 Notes: 10000 C will be created and must be destroyed by the user with `MatDestroy()`. 10001 10002 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10003 10004 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10005 10006 Developer Note: 10007 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10008 10009 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10010 @*/ 10011 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10012 { 10013 PetscFunctionBegin; 10014 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10015 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10016 10017 if (scall == MAT_INITIAL_MATRIX) { 10018 PetscCall(MatProductCreate(A, P, NULL, C)); 10019 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10020 PetscCall(MatProductSetAlgorithm(*C, "default")); 10021 PetscCall(MatProductSetFill(*C, fill)); 10022 10023 (*C)->product->api_user = PETSC_TRUE; 10024 PetscCall(MatProductSetFromOptions(*C)); 10025 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); 10026 PetscCall(MatProductSymbolic(*C)); 10027 } else { /* scall == MAT_REUSE_MATRIX */ 10028 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10029 } 10030 10031 PetscCall(MatProductNumeric(*C)); 10032 (*C)->symmetric = A->symmetric; 10033 (*C)->spd = A->spd; 10034 PetscFunctionReturn(PETSC_SUCCESS); 10035 } 10036 10037 /*@ 10038 MatRARt - Creates the matrix product $C = R * A * R^T$ 10039 10040 Neighbor-wise Collective 10041 10042 Input Parameters: 10043 + A - the matrix 10044 . R - the projection matrix 10045 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10046 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10047 if the result is a dense matrix this is irrelevant 10048 10049 Output Parameter: 10050 . C - the product matrix 10051 10052 Level: intermediate 10053 10054 Notes: 10055 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10056 10057 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10058 10059 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10060 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10061 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10062 We recommend using `MatPtAP()` when possible. 10063 10064 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10065 10066 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10067 @*/ 10068 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10069 { 10070 PetscFunctionBegin; 10071 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10072 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10073 10074 if (scall == MAT_INITIAL_MATRIX) { 10075 PetscCall(MatProductCreate(A, R, NULL, C)); 10076 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10077 PetscCall(MatProductSetAlgorithm(*C, "default")); 10078 PetscCall(MatProductSetFill(*C, fill)); 10079 10080 (*C)->product->api_user = PETSC_TRUE; 10081 PetscCall(MatProductSetFromOptions(*C)); 10082 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); 10083 PetscCall(MatProductSymbolic(*C)); 10084 } else { /* scall == MAT_REUSE_MATRIX */ 10085 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10086 } 10087 10088 PetscCall(MatProductNumeric(*C)); 10089 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10090 PetscFunctionReturn(PETSC_SUCCESS); 10091 } 10092 10093 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10094 { 10095 PetscBool flg = PETSC_TRUE; 10096 10097 PetscFunctionBegin; 10098 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10099 if (scall == MAT_INITIAL_MATRIX) { 10100 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10101 PetscCall(MatProductCreate(A, B, NULL, C)); 10102 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10103 PetscCall(MatProductSetFill(*C, fill)); 10104 } else { /* scall == MAT_REUSE_MATRIX */ 10105 Mat_Product *product = (*C)->product; 10106 10107 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10108 if (flg && product && product->type != ptype) { 10109 PetscCall(MatProductClear(*C)); 10110 product = NULL; 10111 } 10112 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10113 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10114 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10115 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10116 product = (*C)->product; 10117 product->fill = fill; 10118 product->clear = PETSC_TRUE; 10119 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10120 flg = PETSC_FALSE; 10121 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10122 } 10123 } 10124 if (flg) { 10125 (*C)->product->api_user = PETSC_TRUE; 10126 PetscCall(MatProductSetType(*C, ptype)); 10127 PetscCall(MatProductSetFromOptions(*C)); 10128 PetscCall(MatProductSymbolic(*C)); 10129 } 10130 PetscCall(MatProductNumeric(*C)); 10131 PetscFunctionReturn(PETSC_SUCCESS); 10132 } 10133 10134 /*@ 10135 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10136 10137 Neighbor-wise Collective 10138 10139 Input Parameters: 10140 + A - the left matrix 10141 . B - the right matrix 10142 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10143 - 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 10144 if the result is a dense matrix this is irrelevant 10145 10146 Output Parameter: 10147 . C - the product matrix 10148 10149 Notes: 10150 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10151 10152 `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 10153 call to this function with `MAT_INITIAL_MATRIX`. 10154 10155 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10156 10157 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`, 10158 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10159 10160 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10161 10162 Example of Usage: 10163 .vb 10164 MatProductCreate(A,B,NULL,&C); 10165 MatProductSetType(C,MATPRODUCT_AB); 10166 MatProductSymbolic(C); 10167 MatProductNumeric(C); // compute C=A * B 10168 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10169 MatProductNumeric(C); 10170 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10171 MatProductNumeric(C); 10172 .ve 10173 10174 Level: intermediate 10175 10176 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10177 @*/ 10178 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10179 { 10180 PetscFunctionBegin; 10181 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10182 PetscFunctionReturn(PETSC_SUCCESS); 10183 } 10184 10185 /*@ 10186 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10187 10188 Neighbor-wise Collective 10189 10190 Input Parameters: 10191 + A - the left matrix 10192 . B - the right matrix 10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10194 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10195 10196 Output Parameter: 10197 . C - the product matrix 10198 10199 Options Database Key: 10200 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10201 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10202 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10203 10204 Level: intermediate 10205 10206 Notes: 10207 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10208 10209 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10210 10211 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10212 actually needed. 10213 10214 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10215 and for pairs of `MATMPIDENSE` matrices. 10216 10217 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10218 10219 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10220 10221 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10222 @*/ 10223 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10224 { 10225 PetscFunctionBegin; 10226 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10227 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10228 PetscFunctionReturn(PETSC_SUCCESS); 10229 } 10230 10231 /*@ 10232 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10233 10234 Neighbor-wise Collective 10235 10236 Input Parameters: 10237 + A - the left matrix 10238 . B - the right matrix 10239 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10240 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10241 10242 Output Parameter: 10243 . C - the product matrix 10244 10245 Level: intermediate 10246 10247 Notes: 10248 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10249 10250 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10251 10252 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10253 10254 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10255 actually needed. 10256 10257 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10258 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10259 10260 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10261 10262 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10263 @*/ 10264 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10265 { 10266 PetscFunctionBegin; 10267 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10268 PetscFunctionReturn(PETSC_SUCCESS); 10269 } 10270 10271 /*@ 10272 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10273 10274 Neighbor-wise Collective 10275 10276 Input Parameters: 10277 + A - the left matrix 10278 . B - the middle matrix 10279 . C - the right matrix 10280 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10281 - 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 10282 if the result is a dense matrix this is irrelevant 10283 10284 Output Parameter: 10285 . D - the product matrix 10286 10287 Level: intermediate 10288 10289 Notes: 10290 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10291 10292 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10293 10294 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10295 10296 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10297 actually needed. 10298 10299 If you have many matrices with the same non-zero structure to multiply, you 10300 should use `MAT_REUSE_MATRIX` in all calls but the first 10301 10302 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10303 10304 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10305 @*/ 10306 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10307 { 10308 PetscFunctionBegin; 10309 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10310 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10311 10312 if (scall == MAT_INITIAL_MATRIX) { 10313 PetscCall(MatProductCreate(A, B, C, D)); 10314 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10315 PetscCall(MatProductSetAlgorithm(*D, "default")); 10316 PetscCall(MatProductSetFill(*D, fill)); 10317 10318 (*D)->product->api_user = PETSC_TRUE; 10319 PetscCall(MatProductSetFromOptions(*D)); 10320 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, 10321 ((PetscObject)C)->type_name); 10322 PetscCall(MatProductSymbolic(*D)); 10323 } else { /* user may change input matrices when REUSE */ 10324 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10325 } 10326 PetscCall(MatProductNumeric(*D)); 10327 PetscFunctionReturn(PETSC_SUCCESS); 10328 } 10329 10330 /*@ 10331 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10332 10333 Collective 10334 10335 Input Parameters: 10336 + mat - the matrix 10337 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10338 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10339 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10340 10341 Output Parameter: 10342 . matredundant - redundant matrix 10343 10344 Level: advanced 10345 10346 Notes: 10347 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10348 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10349 10350 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10351 calling it. 10352 10353 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10354 10355 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10356 @*/ 10357 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10358 { 10359 MPI_Comm comm; 10360 PetscMPIInt size; 10361 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10362 Mat_Redundant *redund = NULL; 10363 PetscSubcomm psubcomm = NULL; 10364 MPI_Comm subcomm_in = subcomm; 10365 Mat *matseq; 10366 IS isrow, iscol; 10367 PetscBool newsubcomm = PETSC_FALSE; 10368 10369 PetscFunctionBegin; 10370 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10371 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10372 PetscAssertPointer(*matredundant, 5); 10373 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10374 } 10375 10376 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10377 if (size == 1 || nsubcomm == 1) { 10378 if (reuse == MAT_INITIAL_MATRIX) { 10379 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10380 } else { 10381 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"); 10382 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10383 } 10384 PetscFunctionReturn(PETSC_SUCCESS); 10385 } 10386 10387 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10388 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10389 MatCheckPreallocated(mat, 1); 10390 10391 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10392 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10393 /* create psubcomm, then get subcomm */ 10394 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10395 PetscCallMPI(MPI_Comm_size(comm, &size)); 10396 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10397 10398 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10399 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10400 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10401 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10402 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10403 newsubcomm = PETSC_TRUE; 10404 PetscCall(PetscSubcommDestroy(&psubcomm)); 10405 } 10406 10407 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10408 if (reuse == MAT_INITIAL_MATRIX) { 10409 mloc_sub = PETSC_DECIDE; 10410 nloc_sub = PETSC_DECIDE; 10411 if (bs < 1) { 10412 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10413 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10414 } else { 10415 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10416 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10417 } 10418 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10419 rstart = rend - mloc_sub; 10420 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10421 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10422 PetscCall(ISSetIdentity(iscol)); 10423 } else { /* reuse == MAT_REUSE_MATRIX */ 10424 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"); 10425 /* retrieve subcomm */ 10426 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10427 redund = (*matredundant)->redundant; 10428 isrow = redund->isrow; 10429 iscol = redund->iscol; 10430 matseq = redund->matseq; 10431 } 10432 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10433 10434 /* get matredundant over subcomm */ 10435 if (reuse == MAT_INITIAL_MATRIX) { 10436 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10437 10438 /* create a supporting struct and attach it to C for reuse */ 10439 PetscCall(PetscNew(&redund)); 10440 (*matredundant)->redundant = redund; 10441 redund->isrow = isrow; 10442 redund->iscol = iscol; 10443 redund->matseq = matseq; 10444 if (newsubcomm) { 10445 redund->subcomm = subcomm; 10446 } else { 10447 redund->subcomm = MPI_COMM_NULL; 10448 } 10449 } else { 10450 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10451 } 10452 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10453 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10454 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10455 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10456 } 10457 #endif 10458 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10459 PetscFunctionReturn(PETSC_SUCCESS); 10460 } 10461 10462 /*@C 10463 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10464 a given `Mat`. Each submatrix can span multiple procs. 10465 10466 Collective 10467 10468 Input Parameters: 10469 + mat - the matrix 10470 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10471 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10472 10473 Output Parameter: 10474 . subMat - parallel sub-matrices each spanning a given `subcomm` 10475 10476 Level: advanced 10477 10478 Notes: 10479 The submatrix partition across processors is dictated by `subComm` a 10480 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10481 is not restricted to be grouped with consecutive original MPI processes. 10482 10483 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10484 map directly to the layout of the original matrix [wrt the local 10485 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10486 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10487 the `subMat`. However the offDiagMat looses some columns - and this is 10488 reconstructed with `MatSetValues()` 10489 10490 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10491 10492 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10493 @*/ 10494 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10495 { 10496 PetscMPIInt commsize, subCommSize; 10497 10498 PetscFunctionBegin; 10499 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10500 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10501 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10502 10503 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"); 10504 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10505 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10506 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10507 PetscFunctionReturn(PETSC_SUCCESS); 10508 } 10509 10510 /*@ 10511 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10512 10513 Not Collective 10514 10515 Input Parameters: 10516 + mat - matrix to extract local submatrix from 10517 . isrow - local row indices for submatrix 10518 - iscol - local column indices for submatrix 10519 10520 Output Parameter: 10521 . submat - the submatrix 10522 10523 Level: intermediate 10524 10525 Notes: 10526 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10527 10528 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10529 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10530 10531 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10532 `MatSetValuesBlockedLocal()` will also be implemented. 10533 10534 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10535 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10536 10537 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10538 @*/ 10539 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10540 { 10541 PetscFunctionBegin; 10542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10543 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10544 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10545 PetscCheckSameComm(isrow, 2, iscol, 3); 10546 PetscAssertPointer(submat, 4); 10547 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10548 10549 if (mat->ops->getlocalsubmatrix) { 10550 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10551 } else { 10552 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10553 } 10554 PetscFunctionReturn(PETSC_SUCCESS); 10555 } 10556 10557 /*@ 10558 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10559 10560 Not Collective 10561 10562 Input Parameters: 10563 + mat - matrix to extract local submatrix from 10564 . isrow - local row indices for submatrix 10565 . iscol - local column indices for submatrix 10566 - submat - the submatrix 10567 10568 Level: intermediate 10569 10570 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10571 @*/ 10572 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10573 { 10574 PetscFunctionBegin; 10575 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10576 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10577 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10578 PetscCheckSameComm(isrow, 2, iscol, 3); 10579 PetscAssertPointer(submat, 4); 10580 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10581 10582 if (mat->ops->restorelocalsubmatrix) { 10583 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10584 } else { 10585 PetscCall(MatDestroy(submat)); 10586 } 10587 *submat = NULL; 10588 PetscFunctionReturn(PETSC_SUCCESS); 10589 } 10590 10591 /*@ 10592 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10593 10594 Collective 10595 10596 Input Parameter: 10597 . mat - the matrix 10598 10599 Output Parameter: 10600 . is - if any rows have zero diagonals this contains the list of them 10601 10602 Level: developer 10603 10604 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10605 @*/ 10606 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10607 { 10608 PetscFunctionBegin; 10609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10610 PetscValidType(mat, 1); 10611 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10612 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10613 10614 if (!mat->ops->findzerodiagonals) { 10615 Vec diag; 10616 const PetscScalar *a; 10617 PetscInt *rows; 10618 PetscInt rStart, rEnd, r, nrow = 0; 10619 10620 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10621 PetscCall(MatGetDiagonal(mat, diag)); 10622 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10623 PetscCall(VecGetArrayRead(diag, &a)); 10624 for (r = 0; r < rEnd - rStart; ++r) 10625 if (a[r] == 0.0) ++nrow; 10626 PetscCall(PetscMalloc1(nrow, &rows)); 10627 nrow = 0; 10628 for (r = 0; r < rEnd - rStart; ++r) 10629 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10630 PetscCall(VecRestoreArrayRead(diag, &a)); 10631 PetscCall(VecDestroy(&diag)); 10632 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10633 } else { 10634 PetscUseTypeMethod(mat, findzerodiagonals, is); 10635 } 10636 PetscFunctionReturn(PETSC_SUCCESS); 10637 } 10638 10639 /*@ 10640 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10641 10642 Collective 10643 10644 Input Parameter: 10645 . mat - the matrix 10646 10647 Output Parameter: 10648 . is - contains the list of rows with off block diagonal entries 10649 10650 Level: developer 10651 10652 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10653 @*/ 10654 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10655 { 10656 PetscFunctionBegin; 10657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10658 PetscValidType(mat, 1); 10659 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10660 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10661 10662 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10663 PetscFunctionReturn(PETSC_SUCCESS); 10664 } 10665 10666 /*@C 10667 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10668 10669 Collective; No Fortran Support 10670 10671 Input Parameter: 10672 . mat - the matrix 10673 10674 Output Parameter: 10675 . values - the block inverses in column major order (FORTRAN-like) 10676 10677 Level: advanced 10678 10679 Notes: 10680 The size of the blocks is determined by the block size of the matrix. 10681 10682 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10683 10684 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10685 10686 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10687 @*/ 10688 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10689 { 10690 PetscFunctionBegin; 10691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10692 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10693 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10694 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10695 PetscFunctionReturn(PETSC_SUCCESS); 10696 } 10697 10698 /*@ 10699 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10700 10701 Collective; No Fortran Support 10702 10703 Input Parameters: 10704 + mat - the matrix 10705 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10706 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10707 10708 Output Parameter: 10709 . values - the block inverses in column major order (FORTRAN-like) 10710 10711 Level: advanced 10712 10713 Notes: 10714 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10715 10716 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10717 10718 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10719 @*/ 10720 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10721 { 10722 PetscFunctionBegin; 10723 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10726 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10727 PetscFunctionReturn(PETSC_SUCCESS); 10728 } 10729 10730 /*@ 10731 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10732 10733 Collective 10734 10735 Input Parameters: 10736 + A - the matrix 10737 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10738 10739 Level: advanced 10740 10741 Note: 10742 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10743 10744 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10745 @*/ 10746 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10747 { 10748 const PetscScalar *vals; 10749 PetscInt *dnnz; 10750 PetscInt m, rstart, rend, bs, i, j; 10751 10752 PetscFunctionBegin; 10753 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10754 PetscCall(MatGetBlockSize(A, &bs)); 10755 PetscCall(MatGetLocalSize(A, &m, NULL)); 10756 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10757 if (A->rmap->bs > 1) PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); // mpiaij to A and B 10758 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10759 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10760 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10761 PetscCall(PetscFree(dnnz)); 10762 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10763 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10764 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10765 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10766 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10767 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10768 PetscFunctionReturn(PETSC_SUCCESS); 10769 } 10770 10771 /*@ 10772 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10773 via `MatTransposeColoringCreate()`. 10774 10775 Collective 10776 10777 Input Parameter: 10778 . c - coloring context 10779 10780 Level: intermediate 10781 10782 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10783 @*/ 10784 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10785 { 10786 MatTransposeColoring matcolor = *c; 10787 10788 PetscFunctionBegin; 10789 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10790 if (--((PetscObject)matcolor)->refct > 0) { 10791 matcolor = NULL; 10792 PetscFunctionReturn(PETSC_SUCCESS); 10793 } 10794 10795 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10796 PetscCall(PetscFree(matcolor->rows)); 10797 PetscCall(PetscFree(matcolor->den2sp)); 10798 PetscCall(PetscFree(matcolor->colorforcol)); 10799 PetscCall(PetscFree(matcolor->columns)); 10800 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10801 PetscCall(PetscHeaderDestroy(c)); 10802 PetscFunctionReturn(PETSC_SUCCESS); 10803 } 10804 10805 /*@ 10806 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10807 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10808 `MatTransposeColoring` to sparse `B`. 10809 10810 Collective 10811 10812 Input Parameters: 10813 + coloring - coloring context created with `MatTransposeColoringCreate()` 10814 - B - sparse matrix 10815 10816 Output Parameter: 10817 . Btdense - dense matrix $B^T$ 10818 10819 Level: developer 10820 10821 Note: 10822 These are used internally for some implementations of `MatRARt()` 10823 10824 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10825 @*/ 10826 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10827 { 10828 PetscFunctionBegin; 10829 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10830 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10831 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10832 10833 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10834 PetscFunctionReturn(PETSC_SUCCESS); 10835 } 10836 10837 /*@ 10838 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10839 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10840 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10841 $C_{sp}$ from $C_{den}$. 10842 10843 Collective 10844 10845 Input Parameters: 10846 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10847 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10848 10849 Output Parameter: 10850 . Csp - sparse matrix 10851 10852 Level: developer 10853 10854 Note: 10855 These are used internally for some implementations of `MatRARt()` 10856 10857 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10858 @*/ 10859 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10860 { 10861 PetscFunctionBegin; 10862 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10863 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10864 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10865 10866 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10867 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10868 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10869 PetscFunctionReturn(PETSC_SUCCESS); 10870 } 10871 10872 /*@ 10873 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10874 10875 Collective 10876 10877 Input Parameters: 10878 + mat - the matrix product C 10879 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10880 10881 Output Parameter: 10882 . color - the new coloring context 10883 10884 Level: intermediate 10885 10886 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10887 `MatTransColoringApplyDenToSp()` 10888 @*/ 10889 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10890 { 10891 MatTransposeColoring c; 10892 MPI_Comm comm; 10893 10894 PetscFunctionBegin; 10895 PetscAssertPointer(color, 3); 10896 10897 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10898 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10899 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10900 c->ctype = iscoloring->ctype; 10901 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10902 *color = c; 10903 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10904 PetscFunctionReturn(PETSC_SUCCESS); 10905 } 10906 10907 /*@ 10908 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10909 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10910 10911 Not Collective 10912 10913 Input Parameter: 10914 . mat - the matrix 10915 10916 Output Parameter: 10917 . state - the current state 10918 10919 Level: intermediate 10920 10921 Notes: 10922 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10923 different matrices 10924 10925 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10926 10927 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10928 10929 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10930 @*/ 10931 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10932 { 10933 PetscFunctionBegin; 10934 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10935 *state = mat->nonzerostate; 10936 PetscFunctionReturn(PETSC_SUCCESS); 10937 } 10938 10939 /*@ 10940 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10941 matrices from each processor 10942 10943 Collective 10944 10945 Input Parameters: 10946 + comm - the communicators the parallel matrix will live on 10947 . seqmat - the input sequential matrices 10948 . n - number of local columns (or `PETSC_DECIDE`) 10949 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10950 10951 Output Parameter: 10952 . mpimat - the parallel matrix generated 10953 10954 Level: developer 10955 10956 Note: 10957 The number of columns of the matrix in EACH processor MUST be the same. 10958 10959 .seealso: [](ch_matrices), `Mat` 10960 @*/ 10961 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10962 { 10963 PetscMPIInt size; 10964 10965 PetscFunctionBegin; 10966 PetscCallMPI(MPI_Comm_size(comm, &size)); 10967 if (size == 1) { 10968 if (reuse == MAT_INITIAL_MATRIX) { 10969 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10970 } else { 10971 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10972 } 10973 PetscFunctionReturn(PETSC_SUCCESS); 10974 } 10975 10976 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"); 10977 10978 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10979 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10980 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10981 PetscFunctionReturn(PETSC_SUCCESS); 10982 } 10983 10984 /*@ 10985 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10986 10987 Collective 10988 10989 Input Parameters: 10990 + A - the matrix to create subdomains from 10991 - N - requested number of subdomains 10992 10993 Output Parameters: 10994 + n - number of subdomains resulting on this MPI process 10995 - iss - `IS` list with indices of subdomains on this MPI process 10996 10997 Level: advanced 10998 10999 Note: 11000 The number of subdomains must be smaller than the communicator size 11001 11002 .seealso: [](ch_matrices), `Mat`, `IS` 11003 @*/ 11004 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11005 { 11006 MPI_Comm comm, subcomm; 11007 PetscMPIInt size, rank, color; 11008 PetscInt rstart, rend, k; 11009 11010 PetscFunctionBegin; 11011 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11012 PetscCallMPI(MPI_Comm_size(comm, &size)); 11013 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11014 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); 11015 *n = 1; 11016 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11017 color = rank / k; 11018 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11019 PetscCall(PetscMalloc1(1, iss)); 11020 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11021 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11022 PetscCallMPI(MPI_Comm_free(&subcomm)); 11023 PetscFunctionReturn(PETSC_SUCCESS); 11024 } 11025 11026 /*@ 11027 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11028 11029 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11030 If they are not the same, uses `MatMatMatMult()`. 11031 11032 Once the coarse grid problem is constructed, correct for interpolation operators 11033 that are not of full rank, which can legitimately happen in the case of non-nested 11034 geometric multigrid. 11035 11036 Input Parameters: 11037 + restrct - restriction operator 11038 . dA - fine grid matrix 11039 . interpolate - interpolation operator 11040 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11041 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11042 11043 Output Parameter: 11044 . A - the Galerkin coarse matrix 11045 11046 Options Database Key: 11047 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11048 11049 Level: developer 11050 11051 Note: 11052 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11053 11054 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11055 @*/ 11056 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11057 { 11058 IS zerorows; 11059 Vec diag; 11060 11061 PetscFunctionBegin; 11062 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11063 /* Construct the coarse grid matrix */ 11064 if (interpolate == restrct) { 11065 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11066 } else { 11067 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11068 } 11069 11070 /* If the interpolation matrix is not of full rank, A will have zero rows. 11071 This can legitimately happen in the case of non-nested geometric multigrid. 11072 In that event, we set the rows of the matrix to the rows of the identity, 11073 ignoring the equations (as the RHS will also be zero). */ 11074 11075 PetscCall(MatFindZeroRows(*A, &zerorows)); 11076 11077 if (zerorows != NULL) { /* if there are any zero rows */ 11078 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11079 PetscCall(MatGetDiagonal(*A, diag)); 11080 PetscCall(VecISSet(diag, zerorows, 1.0)); 11081 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11082 PetscCall(VecDestroy(&diag)); 11083 PetscCall(ISDestroy(&zerorows)); 11084 } 11085 PetscFunctionReturn(PETSC_SUCCESS); 11086 } 11087 11088 /*@C 11089 MatSetOperation - Allows user to set a matrix operation for any matrix type 11090 11091 Logically Collective 11092 11093 Input Parameters: 11094 + mat - the matrix 11095 . op - the name of the operation 11096 - f - the function that provides the operation 11097 11098 Level: developer 11099 11100 Example Usage: 11101 .vb 11102 extern PetscErrorCode usermult(Mat, Vec, Vec); 11103 11104 PetscCall(MatCreateXXX(comm, ..., &A)); 11105 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11106 .ve 11107 11108 Notes: 11109 See the file `include/petscmat.h` for a complete list of matrix 11110 operations, which all have the form MATOP_<OPERATION>, where 11111 <OPERATION> is the name (in all capital letters) of the 11112 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11113 11114 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11115 sequence as the usual matrix interface routines, since they 11116 are intended to be accessed via the usual matrix interface 11117 routines, e.g., 11118 .vb 11119 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11120 .ve 11121 11122 In particular each function MUST return `PETSC_SUCCESS` on success and 11123 nonzero on failure. 11124 11125 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11126 11127 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11128 @*/ 11129 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11130 { 11131 PetscFunctionBegin; 11132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11133 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11134 (((void (**)(void))mat->ops)[op]) = f; 11135 PetscFunctionReturn(PETSC_SUCCESS); 11136 } 11137 11138 /*@C 11139 MatGetOperation - Gets a matrix operation for any matrix type. 11140 11141 Not Collective 11142 11143 Input Parameters: 11144 + mat - the matrix 11145 - op - the name of the operation 11146 11147 Output Parameter: 11148 . f - the function that provides the operation 11149 11150 Level: developer 11151 11152 Example Usage: 11153 .vb 11154 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11155 11156 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11157 .ve 11158 11159 Notes: 11160 See the file include/petscmat.h for a complete list of matrix 11161 operations, which all have the form MATOP_<OPERATION>, where 11162 <OPERATION> is the name (in all capital letters) of the 11163 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11164 11165 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11166 11167 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11168 @*/ 11169 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11170 { 11171 PetscFunctionBegin; 11172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11173 *f = (((void (**)(void))mat->ops)[op]); 11174 PetscFunctionReturn(PETSC_SUCCESS); 11175 } 11176 11177 /*@ 11178 MatHasOperation - Determines whether the given matrix supports the particular operation. 11179 11180 Not Collective 11181 11182 Input Parameters: 11183 + mat - the matrix 11184 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11185 11186 Output Parameter: 11187 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11188 11189 Level: advanced 11190 11191 Note: 11192 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11193 11194 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11195 @*/ 11196 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11197 { 11198 PetscFunctionBegin; 11199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11200 PetscAssertPointer(has, 3); 11201 if (mat->ops->hasoperation) { 11202 PetscUseTypeMethod(mat, hasoperation, op, has); 11203 } else { 11204 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11205 else { 11206 *has = PETSC_FALSE; 11207 if (op == MATOP_CREATE_SUBMATRIX) { 11208 PetscMPIInt size; 11209 11210 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11211 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11212 } 11213 } 11214 } 11215 PetscFunctionReturn(PETSC_SUCCESS); 11216 } 11217 11218 /*@ 11219 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11220 11221 Collective 11222 11223 Input Parameter: 11224 . mat - the matrix 11225 11226 Output Parameter: 11227 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11228 11229 Level: beginner 11230 11231 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11232 @*/ 11233 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11234 { 11235 PetscFunctionBegin; 11236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11237 PetscValidType(mat, 1); 11238 PetscAssertPointer(cong, 2); 11239 if (!mat->rmap || !mat->cmap) { 11240 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11241 PetscFunctionReturn(PETSC_SUCCESS); 11242 } 11243 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11244 PetscCall(PetscLayoutSetUp(mat->rmap)); 11245 PetscCall(PetscLayoutSetUp(mat->cmap)); 11246 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11247 if (*cong) mat->congruentlayouts = 1; 11248 else mat->congruentlayouts = 0; 11249 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11250 PetscFunctionReturn(PETSC_SUCCESS); 11251 } 11252 11253 PetscErrorCode MatSetInf(Mat A) 11254 { 11255 PetscFunctionBegin; 11256 PetscUseTypeMethod(A, setinf); 11257 PetscFunctionReturn(PETSC_SUCCESS); 11258 } 11259 11260 /*@ 11261 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 11262 and possibly removes small values from the graph structure. 11263 11264 Collective 11265 11266 Input Parameters: 11267 + A - the matrix 11268 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11269 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11270 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11271 . num_idx - size of 'index' array 11272 - index - array of block indices to use for graph strength of connection weight 11273 11274 Output Parameter: 11275 . graph - the resulting graph 11276 11277 Level: advanced 11278 11279 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11280 @*/ 11281 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11282 { 11283 PetscFunctionBegin; 11284 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11285 PetscValidType(A, 1); 11286 PetscValidLogicalCollectiveBool(A, scale, 3); 11287 PetscAssertPointer(graph, 7); 11288 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11289 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11290 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11291 PetscFunctionReturn(PETSC_SUCCESS); 11292 } 11293 11294 /*@ 11295 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11296 meaning the same memory is used for the matrix, and no new memory is allocated. 11297 11298 Collective 11299 11300 Input Parameters: 11301 + A - the matrix 11302 - 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 11303 11304 Level: intermediate 11305 11306 Developer Note: 11307 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11308 of the arrays in the data structure are unneeded. 11309 11310 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11311 @*/ 11312 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11313 { 11314 PetscFunctionBegin; 11315 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11316 PetscUseTypeMethod(A, eliminatezeros, keep); 11317 PetscFunctionReturn(PETSC_SUCCESS); 11318 } 11319