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 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 882 @*/ 883 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 884 { 885 PetscFunctionBegin; 886 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 887 PetscAssertPointer(prefix, 2); 888 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 889 PetscFunctionReturn(PETSC_SUCCESS); 890 } 891 892 /*@ 893 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 894 895 Not Collective 896 897 Input Parameter: 898 . A - the matrix 899 900 Output Parameter: 901 . state - the object state 902 903 Level: advanced 904 905 Note: 906 Object state is an integer which gets increased every time 907 the object is changed. By saving and later querying the object state 908 one can determine whether information about the object is still current. 909 910 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 911 912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 913 @*/ 914 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 915 { 916 PetscFunctionBegin; 917 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 918 PetscAssertPointer(state, 2); 919 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 920 PetscFunctionReturn(PETSC_SUCCESS); 921 } 922 923 /*@ 924 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 925 926 Collective 927 928 Input Parameter: 929 . A - the matrix 930 931 Level: beginner 932 933 Notes: 934 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 935 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 936 makes all of the preallocation space available 937 938 Current values in the matrix are lost in this call 939 940 Currently only supported for `MATAIJ` matrices. 941 942 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 943 @*/ 944 PetscErrorCode MatResetPreallocation(Mat A) 945 { 946 PetscFunctionBegin; 947 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 948 PetscValidType(A, 1); 949 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 950 PetscFunctionReturn(PETSC_SUCCESS); 951 } 952 953 /*@ 954 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 955 956 Collective 957 958 Input Parameter: 959 . A - the matrix 960 961 Level: intermediate 962 963 Notes: 964 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 965 966 Currently only supported for `MATAIJ` matrices. 967 968 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 969 @*/ 970 PetscErrorCode MatResetHash(Mat A) 971 { 972 PetscFunctionBegin; 973 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 974 PetscValidType(A, 1); 975 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()"); 976 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 977 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 978 /* These flags are used to determine whether certain setups occur */ 979 A->was_assembled = PETSC_FALSE; 980 A->assembled = PETSC_FALSE; 981 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 982 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 983 PetscFunctionReturn(PETSC_SUCCESS); 984 } 985 986 /*@ 987 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 988 989 Collective 990 991 Input Parameter: 992 . A - the matrix 993 994 Level: advanced 995 996 Notes: 997 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 998 setting values in the matrix. 999 1000 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1001 1002 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1003 @*/ 1004 PetscErrorCode MatSetUp(Mat A) 1005 { 1006 PetscFunctionBegin; 1007 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1008 if (!((PetscObject)A)->type_name) { 1009 PetscMPIInt size; 1010 1011 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1012 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1013 } 1014 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1015 PetscCall(PetscLayoutSetUp(A->rmap)); 1016 PetscCall(PetscLayoutSetUp(A->cmap)); 1017 A->preallocated = PETSC_TRUE; 1018 PetscFunctionReturn(PETSC_SUCCESS); 1019 } 1020 1021 #if defined(PETSC_HAVE_SAWS) 1022 #include <petscviewersaws.h> 1023 #endif 1024 1025 /* 1026 If threadsafety is on extraneous matrices may be printed 1027 1028 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1029 */ 1030 #if !defined(PETSC_HAVE_THREADSAFETY) 1031 static PetscInt insidematview = 0; 1032 #endif 1033 1034 /*@ 1035 MatViewFromOptions - View properties of the matrix based on options set in the options database 1036 1037 Collective 1038 1039 Input Parameters: 1040 + A - the matrix 1041 . obj - optional additional object that provides the options prefix to use 1042 - name - command line option 1043 1044 Options Database Key: 1045 . -mat_view [viewertype]:... - the viewer and its options 1046 1047 Level: intermediate 1048 1049 Note: 1050 .vb 1051 If no value is provided ascii:stdout is used 1052 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1053 for example ascii::ascii_info prints just the information about the object not all details 1054 unless :append is given filename opens in write mode, overwriting what was already there 1055 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1056 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1057 socket[:port] defaults to the standard output port 1058 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1059 .ve 1060 1061 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1062 @*/ 1063 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1064 { 1065 PetscFunctionBegin; 1066 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1067 #if !defined(PETSC_HAVE_THREADSAFETY) 1068 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1069 #endif 1070 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1071 PetscFunctionReturn(PETSC_SUCCESS); 1072 } 1073 1074 /*@ 1075 MatView - display information about a matrix in a variety ways 1076 1077 Collective on viewer 1078 1079 Input Parameters: 1080 + mat - the matrix 1081 - viewer - visualization context 1082 1083 Options Database Keys: 1084 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1085 . -mat_view ::ascii_info_detail - Prints more detailed info 1086 . -mat_view - Prints matrix in ASCII format 1087 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1088 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1089 . -display <name> - Sets display name (default is host) 1090 . -draw_pause <sec> - Sets number of seconds to pause after display 1091 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1092 . -viewer_socket_machine <machine> - - 1093 . -viewer_socket_port <port> - - 1094 . -mat_view binary - save matrix to file in binary format 1095 - -viewer_binary_filename <name> - - 1096 1097 Level: beginner 1098 1099 Notes: 1100 The available visualization contexts include 1101 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1102 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1103 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1104 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1105 1106 The user can open alternative visualization contexts with 1107 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1108 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1109 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1110 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1111 1112 The user can call `PetscViewerPushFormat()` to specify the output 1113 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1114 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1115 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1116 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1117 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1118 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1119 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1120 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1121 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1122 1123 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1124 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1125 1126 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1127 1128 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1129 viewer is used. 1130 1131 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1132 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1133 1134 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1135 and then use the following mouse functions. 1136 .vb 1137 left mouse: zoom in 1138 middle mouse: zoom out 1139 right mouse: continue with the simulation 1140 .ve 1141 1142 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1143 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1144 @*/ 1145 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1146 { 1147 PetscInt rows, cols, rbs, cbs; 1148 PetscBool isascii, isstring, issaws; 1149 PetscViewerFormat format; 1150 PetscMPIInt size; 1151 1152 PetscFunctionBegin; 1153 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1154 PetscValidType(mat, 1); 1155 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1156 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1157 1158 PetscCall(PetscViewerGetFormat(viewer, &format)); 1159 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1160 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1161 1162 #if !defined(PETSC_HAVE_THREADSAFETY) 1163 insidematview++; 1164 #endif 1165 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1166 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1167 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1168 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"); 1169 1170 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1171 if (isascii) { 1172 if (!mat->preallocated) { 1173 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1174 #if !defined(PETSC_HAVE_THREADSAFETY) 1175 insidematview--; 1176 #endif 1177 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1178 PetscFunctionReturn(PETSC_SUCCESS); 1179 } 1180 if (!mat->assembled) { 1181 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1182 #if !defined(PETSC_HAVE_THREADSAFETY) 1183 insidematview--; 1184 #endif 1185 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1186 PetscFunctionReturn(PETSC_SUCCESS); 1187 } 1188 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1189 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1190 MatNullSpace nullsp, transnullsp; 1191 1192 PetscCall(PetscViewerASCIIPushTab(viewer)); 1193 PetscCall(MatGetSize(mat, &rows, &cols)); 1194 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1195 if (rbs != 1 || cbs != 1) { 1196 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" : "")); 1197 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1198 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1199 if (mat->factortype) { 1200 MatSolverType solver; 1201 PetscCall(MatFactorGetSolverType(mat, &solver)); 1202 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1203 } 1204 if (mat->ops->getinfo) { 1205 MatInfo info; 1206 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1207 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1208 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1209 } 1210 PetscCall(MatGetNullSpace(mat, &nullsp)); 1211 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1212 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1213 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1214 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1215 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1216 PetscCall(PetscViewerASCIIPushTab(viewer)); 1217 PetscCall(MatProductView(mat, viewer)); 1218 PetscCall(PetscViewerASCIIPopTab(viewer)); 1219 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1220 IS tmp; 1221 1222 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1223 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1224 PetscCall(PetscViewerASCIIPushTab(viewer)); 1225 PetscCall(ISView(tmp, viewer)); 1226 PetscCall(PetscViewerASCIIPopTab(viewer)); 1227 PetscCall(ISDestroy(&tmp)); 1228 } 1229 } 1230 } else if (issaws) { 1231 #if defined(PETSC_HAVE_SAWS) 1232 PetscMPIInt rank; 1233 1234 PetscCall(PetscObjectName((PetscObject)mat)); 1235 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1236 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1237 #endif 1238 } else if (isstring) { 1239 const char *type; 1240 PetscCall(MatGetType(mat, &type)); 1241 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1242 PetscTryTypeMethod(mat, view, viewer); 1243 } 1244 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1245 PetscCall(PetscViewerASCIIPushTab(viewer)); 1246 PetscUseTypeMethod(mat, viewnative, viewer); 1247 PetscCall(PetscViewerASCIIPopTab(viewer)); 1248 } else if (mat->ops->view) { 1249 PetscCall(PetscViewerASCIIPushTab(viewer)); 1250 PetscUseTypeMethod(mat, view, viewer); 1251 PetscCall(PetscViewerASCIIPopTab(viewer)); 1252 } 1253 if (isascii) { 1254 PetscCall(PetscViewerGetFormat(viewer, &format)); 1255 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1256 } 1257 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1258 #if !defined(PETSC_HAVE_THREADSAFETY) 1259 insidematview--; 1260 #endif 1261 PetscFunctionReturn(PETSC_SUCCESS); 1262 } 1263 1264 #if defined(PETSC_USE_DEBUG) 1265 #include <../src/sys/totalview/tv_data_display.h> 1266 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1267 { 1268 TV_add_row("Local rows", "int", &mat->rmap->n); 1269 TV_add_row("Local columns", "int", &mat->cmap->n); 1270 TV_add_row("Global rows", "int", &mat->rmap->N); 1271 TV_add_row("Global columns", "int", &mat->cmap->N); 1272 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1273 return TV_format_OK; 1274 } 1275 #endif 1276 1277 /*@ 1278 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1279 with `MatView()`. The matrix format is determined from the options database. 1280 Generates a parallel MPI matrix if the communicator has more than one 1281 processor. The default matrix type is `MATAIJ`. 1282 1283 Collective 1284 1285 Input Parameters: 1286 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1287 or some related function before a call to `MatLoad()` 1288 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1289 1290 Options Database Key: 1291 . -matload_block_size <bs> - set block size 1292 1293 Level: beginner 1294 1295 Notes: 1296 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1297 `Mat` before calling this routine if you wish to set it from the options database. 1298 1299 `MatLoad()` automatically loads into the options database any options 1300 given in the file filename.info where filename is the name of the file 1301 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1302 file will be ignored if you use the -viewer_binary_skip_info option. 1303 1304 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1305 sets the default matrix type AIJ and sets the local and global sizes. 1306 If type and/or size is already set, then the same are used. 1307 1308 In parallel, each processor can load a subset of rows (or the 1309 entire matrix). This routine is especially useful when a large 1310 matrix is stored on disk and only part of it is desired on each 1311 processor. For example, a parallel solver may access only some of 1312 the rows from each processor. The algorithm used here reads 1313 relatively small blocks of data rather than reading the entire 1314 matrix and then subsetting it. 1315 1316 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1317 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1318 or the sequence like 1319 .vb 1320 `PetscViewer` v; 1321 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1322 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1323 `PetscViewerSetFromOptions`(v); 1324 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1325 `PetscViewerFileSetName`(v,"datafile"); 1326 .ve 1327 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1328 .vb 1329 -viewer_type {binary, hdf5} 1330 .ve 1331 1332 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1333 and src/mat/tutorials/ex10.c with the second approach. 1334 1335 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1336 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1337 Multiple objects, both matrices and vectors, can be stored within the same file. 1338 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1339 1340 Most users should not need to know the details of the binary storage 1341 format, since `MatLoad()` and `MatView()` completely hide these details. 1342 But for anyone who is interested, the standard binary matrix storage 1343 format is 1344 1345 .vb 1346 PetscInt MAT_FILE_CLASSID 1347 PetscInt number of rows 1348 PetscInt number of columns 1349 PetscInt total number of nonzeros 1350 PetscInt *number nonzeros in each row 1351 PetscInt *column indices of all nonzeros (starting index is zero) 1352 PetscScalar *values of all nonzeros 1353 .ve 1354 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1355 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 1356 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1357 1358 PETSc automatically does the byte swapping for 1359 machines that store the bytes reversed. Thus if you write your own binary 1360 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1361 and `PetscBinaryWrite()` to see how this may be done. 1362 1363 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1364 Each processor's chunk is loaded independently by its owning MPI process. 1365 Multiple objects, both matrices and vectors, can be stored within the same file. 1366 They are looked up by their PetscObject name. 1367 1368 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1369 by default the same structure and naming of the AIJ arrays and column count 1370 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1371 .vb 1372 save example.mat A b -v7.3 1373 .ve 1374 can be directly read by this routine (see Reference 1 for details). 1375 1376 Depending on your MATLAB version, this format might be a default, 1377 otherwise you can set it as default in Preferences. 1378 1379 Unless -nocompression flag is used to save the file in MATLAB, 1380 PETSc must be configured with ZLIB package. 1381 1382 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1383 1384 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1385 1386 Corresponding `MatView()` is not yet implemented. 1387 1388 The loaded matrix is actually a transpose of the original one in MATLAB, 1389 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1390 With this format, matrix is automatically transposed by PETSc, 1391 unless the matrix is marked as SPD or symmetric 1392 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1393 1394 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1395 1396 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1397 @*/ 1398 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1399 { 1400 PetscBool flg; 1401 1402 PetscFunctionBegin; 1403 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1404 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1405 1406 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1407 1408 flg = PETSC_FALSE; 1409 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1410 if (flg) { 1411 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1412 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1413 } 1414 flg = PETSC_FALSE; 1415 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1416 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1417 1418 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1419 PetscUseTypeMethod(mat, load, viewer); 1420 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1421 PetscFunctionReturn(PETSC_SUCCESS); 1422 } 1423 1424 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1425 { 1426 Mat_Redundant *redund = *redundant; 1427 1428 PetscFunctionBegin; 1429 if (redund) { 1430 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1431 PetscCall(ISDestroy(&redund->isrow)); 1432 PetscCall(ISDestroy(&redund->iscol)); 1433 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1434 } else { 1435 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1436 PetscCall(PetscFree(redund->sbuf_j)); 1437 PetscCall(PetscFree(redund->sbuf_a)); 1438 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1439 PetscCall(PetscFree(redund->rbuf_j[i])); 1440 PetscCall(PetscFree(redund->rbuf_a[i])); 1441 } 1442 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1443 } 1444 1445 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1446 PetscCall(PetscFree(redund)); 1447 } 1448 PetscFunctionReturn(PETSC_SUCCESS); 1449 } 1450 1451 /*@ 1452 MatDestroy - Frees space taken by a matrix. 1453 1454 Collective 1455 1456 Input Parameter: 1457 . A - the matrix 1458 1459 Level: beginner 1460 1461 Developer Note: 1462 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1463 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1464 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1465 if changes are needed here. 1466 1467 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1468 @*/ 1469 PetscErrorCode MatDestroy(Mat *A) 1470 { 1471 PetscFunctionBegin; 1472 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1473 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1474 if (--((PetscObject)*A)->refct > 0) { 1475 *A = NULL; 1476 PetscFunctionReturn(PETSC_SUCCESS); 1477 } 1478 1479 /* if memory was published with SAWs then destroy it */ 1480 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1481 PetscTryTypeMethod(*A, destroy); 1482 1483 PetscCall(PetscFree((*A)->factorprefix)); 1484 PetscCall(PetscFree((*A)->defaultvectype)); 1485 PetscCall(PetscFree((*A)->defaultrandtype)); 1486 PetscCall(PetscFree((*A)->bsizes)); 1487 PetscCall(PetscFree((*A)->solvertype)); 1488 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1489 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1490 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1491 PetscCall(MatProductClear(*A)); 1492 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1493 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1494 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1495 PetscCall(MatDestroy(&(*A)->schur)); 1496 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1497 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1498 PetscCall(PetscHeaderDestroy(A)); 1499 PetscFunctionReturn(PETSC_SUCCESS); 1500 } 1501 1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1503 /*@ 1504 MatSetValues - Inserts or adds a block of values into a matrix. 1505 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1506 MUST be called after all calls to `MatSetValues()` have been completed. 1507 1508 Not Collective 1509 1510 Input Parameters: 1511 + mat - the matrix 1512 . v - a logically two-dimensional array of values 1513 . m - the number of rows 1514 . idxm - the global indices of the rows 1515 . n - the number of columns 1516 . idxn - the global indices of the columns 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirichlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 Fortran Notes: 1541 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1542 .vb 1543 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1544 .ve 1545 1546 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1547 1548 Developer Note: 1549 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1550 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1551 1552 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1553 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1554 @*/ 1555 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1556 { 1557 PetscFunctionBeginHot; 1558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1559 PetscValidType(mat, 1); 1560 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1561 PetscAssertPointer(idxm, 3); 1562 PetscAssertPointer(idxn, 5); 1563 MatCheckPreallocated(mat, 1); 1564 1565 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1566 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1567 1568 if (PetscDefined(USE_DEBUG)) { 1569 PetscInt i, j; 1570 1571 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1572 if (v) { 1573 for (i = 0; i < m; i++) { 1574 for (j = 0; j < n; j++) { 1575 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1576 #if defined(PETSC_USE_COMPLEX) 1577 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]); 1578 #else 1579 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]); 1580 #endif 1581 } 1582 } 1583 } 1584 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); 1585 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); 1586 } 1587 1588 if (mat->assembled) { 1589 mat->was_assembled = PETSC_TRUE; 1590 mat->assembled = PETSC_FALSE; 1591 } 1592 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1593 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1594 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1595 PetscFunctionReturn(PETSC_SUCCESS); 1596 } 1597 1598 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1599 /*@ 1600 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1601 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1602 MUST be called after all calls to `MatSetValues()` have been completed. 1603 1604 Not Collective 1605 1606 Input Parameters: 1607 + mat - the matrix 1608 . v - a logically two-dimensional array of values 1609 . ism - the rows to provide 1610 . isn - the columns to provide 1611 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1612 1613 Level: beginner 1614 1615 Notes: 1616 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1617 1618 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1619 options cannot be mixed without intervening calls to the assembly 1620 routines. 1621 1622 `MatSetValues()` uses 0-based row and column numbers in Fortran 1623 as well as in C. 1624 1625 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1626 simply ignored. This allows easily inserting element stiffness matrices 1627 with homogeneous Dirichlet boundary conditions that you don't want represented 1628 in the matrix. 1629 1630 Efficiency Alert: 1631 The routine `MatSetValuesBlocked()` may offer much better efficiency 1632 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1633 1634 This is currently not optimized for any particular `ISType` 1635 1636 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1637 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1638 @*/ 1639 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1640 { 1641 PetscInt m, n; 1642 const PetscInt *rows, *cols; 1643 1644 PetscFunctionBeginHot; 1645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1646 PetscCall(ISGetIndices(ism, &rows)); 1647 PetscCall(ISGetIndices(isn, &cols)); 1648 PetscCall(ISGetLocalSize(ism, &m)); 1649 PetscCall(ISGetLocalSize(isn, &n)); 1650 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1651 PetscCall(ISRestoreIndices(ism, &rows)); 1652 PetscCall(ISRestoreIndices(isn, &cols)); 1653 PetscFunctionReturn(PETSC_SUCCESS); 1654 } 1655 1656 /*@ 1657 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1658 values into a matrix 1659 1660 Not Collective 1661 1662 Input Parameters: 1663 + mat - the matrix 1664 . row - the (block) row to set 1665 - v - a logically two-dimensional array of values 1666 1667 Level: intermediate 1668 1669 Notes: 1670 The values, `v`, are column-oriented (for the block version) and sorted 1671 1672 All the nonzero values in `row` must be provided 1673 1674 The matrix must have previously had its column indices set, likely by having been assembled. 1675 1676 `row` must belong to this MPI process 1677 1678 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1679 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1680 @*/ 1681 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1682 { 1683 PetscInt globalrow; 1684 1685 PetscFunctionBegin; 1686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1687 PetscValidType(mat, 1); 1688 PetscAssertPointer(v, 3); 1689 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1690 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1691 PetscFunctionReturn(PETSC_SUCCESS); 1692 } 1693 1694 /*@ 1695 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1696 values into a matrix 1697 1698 Not Collective 1699 1700 Input Parameters: 1701 + mat - the matrix 1702 . row - the (block) row to set 1703 - 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 1704 1705 Level: advanced 1706 1707 Notes: 1708 The values, `v`, are column-oriented for the block version. 1709 1710 All the nonzeros in `row` must be provided 1711 1712 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1713 1714 `row` must belong to this process 1715 1716 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1717 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1718 @*/ 1719 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1720 { 1721 PetscFunctionBeginHot; 1722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1723 PetscValidType(mat, 1); 1724 MatCheckPreallocated(mat, 1); 1725 PetscAssertPointer(v, 3); 1726 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1727 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1728 mat->insertmode = INSERT_VALUES; 1729 1730 if (mat->assembled) { 1731 mat->was_assembled = PETSC_TRUE; 1732 mat->assembled = PETSC_FALSE; 1733 } 1734 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1735 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1736 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1737 PetscFunctionReturn(PETSC_SUCCESS); 1738 } 1739 1740 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1741 /*@ 1742 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1743 Using structured grid indexing 1744 1745 Not Collective 1746 1747 Input Parameters: 1748 + mat - the matrix 1749 . m - number of rows being entered 1750 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1751 . n - number of columns being entered 1752 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1753 . v - a logically two-dimensional array of values 1754 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1755 1756 Level: beginner 1757 1758 Notes: 1759 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1760 1761 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1762 options cannot be mixed without intervening calls to the assembly 1763 routines. 1764 1765 The grid coordinates are across the entire grid, not just the local portion 1766 1767 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1768 as well as in C. 1769 1770 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1771 1772 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1773 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1774 1775 The columns and rows in the stencil passed in MUST be contained within the 1776 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1777 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1778 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1779 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1780 1781 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1782 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1783 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1784 `DM_BOUNDARY_PERIODIC` boundary type. 1785 1786 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 1787 a single value per point) you can skip filling those indices. 1788 1789 Inspired by the structured grid interface to the HYPRE package 1790 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1791 1792 Efficiency Alert: 1793 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1794 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1795 1796 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1797 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1798 @*/ 1799 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscAssertPointer(idxm, 3); 1810 PetscAssertPointer(idxn, 5); 1811 1812 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1813 jdxm = buf; 1814 jdxn = buf + m; 1815 } else { 1816 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1817 jdxm = bufm; 1818 jdxn = bufn; 1819 } 1820 for (i = 0; i < m; i++) { 1821 for (j = 0; j < 3 - sdim; j++) dxm++; 1822 tmp = *dxm++ - starts[0]; 1823 for (j = 0; j < dim - 1; j++) { 1824 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1825 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1826 } 1827 if (mat->stencil.noc) dxm++; 1828 jdxm[i] = tmp; 1829 } 1830 for (i = 0; i < n; i++) { 1831 for (j = 0; j < 3 - sdim; j++) dxn++; 1832 tmp = *dxn++ - starts[0]; 1833 for (j = 0; j < dim - 1; j++) { 1834 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1835 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1836 } 1837 if (mat->stencil.noc) dxn++; 1838 jdxn[i] = tmp; 1839 } 1840 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1841 PetscCall(PetscFree2(bufm, bufn)); 1842 PetscFunctionReturn(PETSC_SUCCESS); 1843 } 1844 1845 /*@ 1846 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1847 Using structured grid indexing 1848 1849 Not Collective 1850 1851 Input Parameters: 1852 + mat - the matrix 1853 . m - number of rows being entered 1854 . idxm - grid coordinates for matrix rows being entered 1855 . n - number of columns being entered 1856 . idxn - grid coordinates for matrix columns being entered 1857 . v - a logically two-dimensional array of values 1858 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1859 1860 Level: beginner 1861 1862 Notes: 1863 By default the values, `v`, are row-oriented and unsorted. 1864 See `MatSetOption()` for other options. 1865 1866 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1867 options cannot be mixed without intervening calls to the assembly 1868 routines. 1869 1870 The grid coordinates are across the entire grid, not just the local portion 1871 1872 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1873 as well as in C. 1874 1875 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1876 1877 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1878 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1879 1880 The columns and rows in the stencil passed in MUST be contained within the 1881 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1882 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1883 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1884 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1885 1886 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1887 simply ignored. This allows easily inserting element stiffness matrices 1888 with homogeneous Dirichlet boundary conditions that you don't want represented 1889 in the matrix. 1890 1891 Inspired by the structured grid interface to the HYPRE package 1892 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1893 1894 Fortran Note: 1895 `idxm` and `idxn` should be declared as 1896 .vb 1897 MatStencil idxm(4,m),idxn(4,n) 1898 .ve 1899 and the values inserted using 1900 .vb 1901 idxm(MatStencil_i,1) = i 1902 idxm(MatStencil_j,1) = j 1903 idxm(MatStencil_k,1) = k 1904 etc 1905 .ve 1906 1907 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1908 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1909 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1910 @*/ 1911 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1912 { 1913 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1914 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1915 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1916 1917 PetscFunctionBegin; 1918 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1920 PetscValidType(mat, 1); 1921 PetscAssertPointer(idxm, 3); 1922 PetscAssertPointer(idxn, 5); 1923 PetscAssertPointer(v, 6); 1924 1925 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1926 jdxm = buf; 1927 jdxn = buf + m; 1928 } else { 1929 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1930 jdxm = bufm; 1931 jdxn = bufn; 1932 } 1933 for (i = 0; i < m; i++) { 1934 for (j = 0; j < 3 - sdim; j++) dxm++; 1935 tmp = *dxm++ - starts[0]; 1936 for (j = 0; j < sdim - 1; j++) { 1937 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1938 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1939 } 1940 dxm++; 1941 jdxm[i] = tmp; 1942 } 1943 for (i = 0; i < n; i++) { 1944 for (j = 0; j < 3 - sdim; j++) dxn++; 1945 tmp = *dxn++ - starts[0]; 1946 for (j = 0; j < sdim - 1; j++) { 1947 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1948 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1949 } 1950 dxn++; 1951 jdxn[i] = tmp; 1952 } 1953 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1954 PetscCall(PetscFree2(bufm, bufn)); 1955 PetscFunctionReturn(PETSC_SUCCESS); 1956 } 1957 1958 /*@ 1959 MatSetStencil - Sets the grid information for setting values into a matrix via 1960 `MatSetValuesStencil()` 1961 1962 Not Collective 1963 1964 Input Parameters: 1965 + mat - the matrix 1966 . dim - dimension of the grid 1, 2, or 3 1967 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1968 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1969 - dof - number of degrees of freedom per node 1970 1971 Level: beginner 1972 1973 Notes: 1974 Inspired by the structured grid interface to the HYPRE package 1975 (www.llnl.gov/CASC/hyper) 1976 1977 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1978 user. 1979 1980 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1981 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1982 @*/ 1983 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1984 { 1985 PetscFunctionBegin; 1986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1987 PetscAssertPointer(dims, 3); 1988 PetscAssertPointer(starts, 4); 1989 1990 mat->stencil.dim = dim + (dof > 1); 1991 for (PetscInt i = 0; i < dim; i++) { 1992 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1993 mat->stencil.starts[i] = starts[dim - i - 1]; 1994 } 1995 mat->stencil.dims[dim] = dof; 1996 mat->stencil.starts[dim] = 0; 1997 mat->stencil.noc = (PetscBool)(dof == 1); 1998 PetscFunctionReturn(PETSC_SUCCESS); 1999 } 2000 2001 /*@ 2002 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2003 2004 Not Collective 2005 2006 Input Parameters: 2007 + mat - the matrix 2008 . v - a logically two-dimensional array of values 2009 . m - the number of block rows 2010 . idxm - the global block indices 2011 . n - the number of block columns 2012 . idxn - the global block indices 2013 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2014 2015 Level: intermediate 2016 2017 Notes: 2018 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2019 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2020 2021 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2022 NOT the total number of rows/columns; for example, if the block size is 2 and 2023 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2024 The values in `idxm` would be 1 2; that is the first index for each block divided by 2025 the block size. 2026 2027 You must call `MatSetBlockSize()` when constructing this matrix (before 2028 preallocating it). 2029 2030 By default the values, `v`, are row-oriented, so the layout of 2031 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2032 2033 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2034 options cannot be mixed without intervening calls to the assembly 2035 routines. 2036 2037 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2038 as well as in C. 2039 2040 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2041 simply ignored. This allows easily inserting element stiffness matrices 2042 with homogeneous Dirichlet boundary conditions that you don't want represented 2043 in the matrix. 2044 2045 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2046 internal searching must be done to determine where to place the 2047 data in the matrix storage space. By instead inserting blocks of 2048 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2049 reduced. 2050 2051 Example: 2052 .vb 2053 Suppose m=n=2 and block size(bs) = 2 The array is 2054 2055 1 2 | 3 4 2056 5 6 | 7 8 2057 - - - | - - - 2058 9 10 | 11 12 2059 13 14 | 15 16 2060 2061 v[] should be passed in like 2062 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2063 2064 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2065 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2066 .ve 2067 2068 Fortran Notes: 2069 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2070 .vb 2071 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2072 .ve 2073 2074 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2075 2076 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2077 @*/ 2078 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2079 { 2080 PetscFunctionBeginHot; 2081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2082 PetscValidType(mat, 1); 2083 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2084 PetscAssertPointer(idxm, 3); 2085 PetscAssertPointer(idxn, 5); 2086 MatCheckPreallocated(mat, 1); 2087 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2088 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2089 if (PetscDefined(USE_DEBUG)) { 2090 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2091 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2092 } 2093 if (PetscDefined(USE_DEBUG)) { 2094 PetscInt rbs, cbs, M, N, i; 2095 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2096 PetscCall(MatGetSize(mat, &M, &N)); 2097 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); 2098 for (i = 0; i < n; i++) 2099 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); 2100 } 2101 if (mat->assembled) { 2102 mat->was_assembled = PETSC_TRUE; 2103 mat->assembled = PETSC_FALSE; 2104 } 2105 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2106 if (mat->ops->setvaluesblocked) { 2107 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2108 } else { 2109 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2110 PetscInt i, j, bs, cbs; 2111 2112 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2113 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2114 iidxm = buf; 2115 iidxn = buf + m * bs; 2116 } else { 2117 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2118 iidxm = bufr; 2119 iidxn = bufc; 2120 } 2121 for (i = 0; i < m; i++) { 2122 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2123 } 2124 if (m != n || bs != cbs || idxm != idxn) { 2125 for (i = 0; i < n; i++) { 2126 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2127 } 2128 } else iidxn = iidxm; 2129 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2130 PetscCall(PetscFree2(bufr, bufc)); 2131 } 2132 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2133 PetscFunctionReturn(PETSC_SUCCESS); 2134 } 2135 2136 /*@ 2137 MatGetValues - Gets a block of local values from a matrix. 2138 2139 Not Collective; can only return values that are owned by the give process 2140 2141 Input Parameters: 2142 + mat - the matrix 2143 . v - a logically two-dimensional array for storing the values 2144 . m - the number of rows 2145 . idxm - the global indices of the rows 2146 . n - the number of columns 2147 - idxn - the global indices of the columns 2148 2149 Level: advanced 2150 2151 Notes: 2152 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2153 The values, `v`, are then returned in a row-oriented format, 2154 analogous to that used by default in `MatSetValues()`. 2155 2156 `MatGetValues()` uses 0-based row and column numbers in 2157 Fortran as well as in C. 2158 2159 `MatGetValues()` requires that the matrix has been assembled 2160 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2161 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2162 without intermediate matrix assembly. 2163 2164 Negative row or column indices will be ignored and those locations in `v` will be 2165 left unchanged. 2166 2167 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2168 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2169 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2170 2171 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2172 @*/ 2173 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2174 { 2175 PetscFunctionBegin; 2176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2177 PetscValidType(mat, 1); 2178 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2179 PetscAssertPointer(idxm, 3); 2180 PetscAssertPointer(idxn, 5); 2181 PetscAssertPointer(v, 6); 2182 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2183 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2184 MatCheckPreallocated(mat, 1); 2185 2186 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2187 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2188 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2189 PetscFunctionReturn(PETSC_SUCCESS); 2190 } 2191 2192 /*@ 2193 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2194 defined previously by `MatSetLocalToGlobalMapping()` 2195 2196 Not Collective 2197 2198 Input Parameters: 2199 + mat - the matrix 2200 . nrow - number of rows 2201 . irow - the row local indices 2202 . ncol - number of columns 2203 - icol - the column local indices 2204 2205 Output Parameter: 2206 . y - a logically two-dimensional array of values 2207 2208 Level: advanced 2209 2210 Notes: 2211 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2212 2213 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, 2214 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2215 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2216 with `MatSetLocalToGlobalMapping()`. 2217 2218 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2219 `MatSetValuesLocal()`, `MatGetValues()` 2220 @*/ 2221 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2222 { 2223 PetscFunctionBeginHot; 2224 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2225 PetscValidType(mat, 1); 2226 MatCheckPreallocated(mat, 1); 2227 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2228 PetscAssertPointer(irow, 3); 2229 PetscAssertPointer(icol, 5); 2230 if (PetscDefined(USE_DEBUG)) { 2231 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2232 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2233 } 2234 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2235 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2236 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2237 else { 2238 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2239 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2240 irowm = buf; 2241 icolm = buf + nrow; 2242 } else { 2243 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2244 irowm = bufr; 2245 icolm = bufc; 2246 } 2247 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2248 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2249 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2250 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2251 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2252 PetscCall(PetscFree2(bufr, bufc)); 2253 } 2254 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2255 PetscFunctionReturn(PETSC_SUCCESS); 2256 } 2257 2258 /*@ 2259 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2260 the same size. Currently, this can only be called once and creates the given matrix. 2261 2262 Not Collective 2263 2264 Input Parameters: 2265 + mat - the matrix 2266 . nb - the number of blocks 2267 . bs - the number of rows (and columns) in each block 2268 . rows - a concatenation of the rows for each block 2269 - v - a concatenation of logically two-dimensional arrays of values 2270 2271 Level: advanced 2272 2273 Notes: 2274 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2275 2276 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2277 2278 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2279 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2280 @*/ 2281 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2282 { 2283 PetscFunctionBegin; 2284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2285 PetscValidType(mat, 1); 2286 PetscAssertPointer(rows, 4); 2287 PetscAssertPointer(v, 5); 2288 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2289 2290 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2291 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2292 else { 2293 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2294 } 2295 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2296 PetscFunctionReturn(PETSC_SUCCESS); 2297 } 2298 2299 /*@ 2300 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2301 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2302 using a local (per-processor) numbering. 2303 2304 Not Collective 2305 2306 Input Parameters: 2307 + x - the matrix 2308 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2309 - cmapping - column mapping 2310 2311 Level: intermediate 2312 2313 Note: 2314 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2315 2316 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2317 @*/ 2318 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2319 { 2320 PetscFunctionBegin; 2321 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2322 PetscValidType(x, 1); 2323 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2324 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2325 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2326 else { 2327 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2328 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2329 } 2330 PetscFunctionReturn(PETSC_SUCCESS); 2331 } 2332 2333 /*@ 2334 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2335 2336 Not Collective 2337 2338 Input Parameter: 2339 . A - the matrix 2340 2341 Output Parameters: 2342 + rmapping - row mapping 2343 - cmapping - column mapping 2344 2345 Level: advanced 2346 2347 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2348 @*/ 2349 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2350 { 2351 PetscFunctionBegin; 2352 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2353 PetscValidType(A, 1); 2354 if (rmapping) { 2355 PetscAssertPointer(rmapping, 2); 2356 *rmapping = A->rmap->mapping; 2357 } 2358 if (cmapping) { 2359 PetscAssertPointer(cmapping, 3); 2360 *cmapping = A->cmap->mapping; 2361 } 2362 PetscFunctionReturn(PETSC_SUCCESS); 2363 } 2364 2365 /*@ 2366 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2367 2368 Logically Collective 2369 2370 Input Parameters: 2371 + A - the matrix 2372 . rmap - row layout 2373 - cmap - column layout 2374 2375 Level: advanced 2376 2377 Note: 2378 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2379 2380 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2381 @*/ 2382 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2383 { 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2386 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2387 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2388 PetscFunctionReturn(PETSC_SUCCESS); 2389 } 2390 2391 /*@ 2392 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2393 2394 Not Collective 2395 2396 Input Parameter: 2397 . A - the matrix 2398 2399 Output Parameters: 2400 + rmap - row layout 2401 - cmap - column layout 2402 2403 Level: advanced 2404 2405 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2406 @*/ 2407 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2408 { 2409 PetscFunctionBegin; 2410 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2411 PetscValidType(A, 1); 2412 if (rmap) { 2413 PetscAssertPointer(rmap, 2); 2414 *rmap = A->rmap; 2415 } 2416 if (cmap) { 2417 PetscAssertPointer(cmap, 3); 2418 *cmap = A->cmap; 2419 } 2420 PetscFunctionReturn(PETSC_SUCCESS); 2421 } 2422 2423 /*@ 2424 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2425 using a local numbering of the rows and columns. 2426 2427 Not Collective 2428 2429 Input Parameters: 2430 + mat - the matrix 2431 . nrow - number of rows 2432 . irow - the row local indices 2433 . ncol - number of columns 2434 . icol - the column local indices 2435 . y - a logically two-dimensional array of values 2436 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2437 2438 Level: intermediate 2439 2440 Notes: 2441 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2442 2443 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2444 options cannot be mixed without intervening calls to the assembly 2445 routines. 2446 2447 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2448 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2449 2450 Fortran Notes: 2451 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2452 .vb 2453 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2454 .ve 2455 2456 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2457 2458 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2459 `MatGetValuesLocal()` 2460 @*/ 2461 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2462 { 2463 PetscFunctionBeginHot; 2464 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2465 PetscValidType(mat, 1); 2466 MatCheckPreallocated(mat, 1); 2467 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2468 PetscAssertPointer(irow, 3); 2469 PetscAssertPointer(icol, 5); 2470 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2471 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2472 if (PetscDefined(USE_DEBUG)) { 2473 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2474 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2475 } 2476 2477 if (mat->assembled) { 2478 mat->was_assembled = PETSC_TRUE; 2479 mat->assembled = PETSC_FALSE; 2480 } 2481 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2482 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2483 else { 2484 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2485 const PetscInt *irowm, *icolm; 2486 2487 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2488 bufr = buf; 2489 bufc = buf + nrow; 2490 irowm = bufr; 2491 icolm = bufc; 2492 } else { 2493 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2494 irowm = bufr; 2495 icolm = bufc; 2496 } 2497 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2498 else irowm = irow; 2499 if (mat->cmap->mapping) { 2500 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2501 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2502 } else icolm = irowm; 2503 } else icolm = icol; 2504 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2505 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2506 } 2507 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2508 PetscFunctionReturn(PETSC_SUCCESS); 2509 } 2510 2511 /*@ 2512 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2513 using a local ordering of the nodes a block at a time. 2514 2515 Not Collective 2516 2517 Input Parameters: 2518 + mat - the matrix 2519 . nrow - number of rows 2520 . irow - the row local indices 2521 . ncol - number of columns 2522 . icol - the column local indices 2523 . y - a logically two-dimensional array of values 2524 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2525 2526 Level: intermediate 2527 2528 Notes: 2529 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2530 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2531 2532 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2533 options cannot be mixed without intervening calls to the assembly 2534 routines. 2535 2536 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2537 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2538 2539 Fortran Notes: 2540 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2541 .vb 2542 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2543 .ve 2544 2545 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2546 2547 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2548 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2549 @*/ 2550 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2551 { 2552 PetscFunctionBeginHot; 2553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2554 PetscValidType(mat, 1); 2555 MatCheckPreallocated(mat, 1); 2556 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2557 PetscAssertPointer(irow, 3); 2558 PetscAssertPointer(icol, 5); 2559 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2560 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2561 if (PetscDefined(USE_DEBUG)) { 2562 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2563 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); 2564 } 2565 2566 if (mat->assembled) { 2567 mat->was_assembled = PETSC_TRUE; 2568 mat->assembled = PETSC_FALSE; 2569 } 2570 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2571 PetscInt irbs, rbs; 2572 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2573 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2574 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2575 } 2576 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2577 PetscInt icbs, cbs; 2578 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2579 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2580 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2581 } 2582 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2583 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2584 else { 2585 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2586 const PetscInt *irowm, *icolm; 2587 2588 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2589 bufr = buf; 2590 bufc = buf + nrow; 2591 irowm = bufr; 2592 icolm = bufc; 2593 } else { 2594 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2595 irowm = bufr; 2596 icolm = bufc; 2597 } 2598 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2599 else irowm = irow; 2600 if (mat->cmap->mapping) { 2601 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2602 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2603 } else icolm = irowm; 2604 } else icolm = icol; 2605 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2606 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2607 } 2608 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2609 PetscFunctionReturn(PETSC_SUCCESS); 2610 } 2611 2612 /*@ 2613 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2614 2615 Collective 2616 2617 Input Parameters: 2618 + mat - the matrix 2619 - x - the vector to be multiplied 2620 2621 Output Parameter: 2622 . y - the result 2623 2624 Level: developer 2625 2626 Note: 2627 The vectors `x` and `y` cannot be the same. I.e., one cannot 2628 call `MatMultDiagonalBlock`(A,y,y). 2629 2630 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2631 @*/ 2632 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2633 { 2634 PetscFunctionBegin; 2635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2636 PetscValidType(mat, 1); 2637 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2638 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2639 2640 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2641 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2642 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2643 MatCheckPreallocated(mat, 1); 2644 2645 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2646 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2647 PetscFunctionReturn(PETSC_SUCCESS); 2648 } 2649 2650 /*@ 2651 MatMult - Computes the matrix-vector product, $y = Ax$. 2652 2653 Neighbor-wise Collective 2654 2655 Input Parameters: 2656 + mat - the matrix 2657 - x - the vector to be multiplied 2658 2659 Output Parameter: 2660 . y - the result 2661 2662 Level: beginner 2663 2664 Note: 2665 The vectors `x` and `y` cannot be the same. I.e., one cannot 2666 call `MatMult`(A,y,y). 2667 2668 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2669 @*/ 2670 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2671 { 2672 PetscFunctionBegin; 2673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2674 PetscValidType(mat, 1); 2675 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2676 VecCheckAssembled(x); 2677 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2678 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2679 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2680 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2681 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); 2682 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); 2683 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); 2684 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); 2685 PetscCall(VecSetErrorIfLocked(y, 3)); 2686 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2687 MatCheckPreallocated(mat, 1); 2688 2689 PetscCall(VecLockReadPush(x)); 2690 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2691 PetscUseTypeMethod(mat, mult, x, y); 2692 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2693 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2694 PetscCall(VecLockReadPop(x)); 2695 PetscFunctionReturn(PETSC_SUCCESS); 2696 } 2697 2698 /*@ 2699 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2700 2701 Neighbor-wise Collective 2702 2703 Input Parameters: 2704 + mat - the matrix 2705 - x - the vector to be multiplied 2706 2707 Output Parameter: 2708 . y - the result 2709 2710 Level: beginner 2711 2712 Notes: 2713 The vectors `x` and `y` cannot be the same. I.e., one cannot 2714 call `MatMultTranspose`(A,y,y). 2715 2716 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2717 use `MatMultHermitianTranspose()` 2718 2719 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2720 @*/ 2721 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2722 { 2723 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2724 2725 PetscFunctionBegin; 2726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2727 PetscValidType(mat, 1); 2728 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2729 VecCheckAssembled(x); 2730 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2731 2732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2734 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2735 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); 2736 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); 2737 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); 2738 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); 2739 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2740 MatCheckPreallocated(mat, 1); 2741 2742 if (!mat->ops->multtranspose) { 2743 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2744 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); 2745 } else op = mat->ops->multtranspose; 2746 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2747 PetscCall(VecLockReadPush(x)); 2748 PetscCall((*op)(mat, x, y)); 2749 PetscCall(VecLockReadPop(x)); 2750 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2751 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2752 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2753 PetscFunctionReturn(PETSC_SUCCESS); 2754 } 2755 2756 /*@ 2757 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2758 2759 Neighbor-wise Collective 2760 2761 Input Parameters: 2762 + mat - the matrix 2763 - x - the vector to be multiplied 2764 2765 Output Parameter: 2766 . y - the result 2767 2768 Level: beginner 2769 2770 Notes: 2771 The vectors `x` and `y` cannot be the same. I.e., one cannot 2772 call `MatMultHermitianTranspose`(A,y,y). 2773 2774 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2775 2776 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2777 2778 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2779 @*/ 2780 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2781 { 2782 PetscFunctionBegin; 2783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2784 PetscValidType(mat, 1); 2785 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2786 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2787 2788 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2789 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2790 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2791 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); 2792 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); 2793 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); 2794 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); 2795 MatCheckPreallocated(mat, 1); 2796 2797 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2798 #if defined(PETSC_USE_COMPLEX) 2799 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2800 PetscCall(VecLockReadPush(x)); 2801 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2802 else PetscUseTypeMethod(mat, mult, x, y); 2803 PetscCall(VecLockReadPop(x)); 2804 } else { 2805 Vec w; 2806 PetscCall(VecDuplicate(x, &w)); 2807 PetscCall(VecCopy(x, w)); 2808 PetscCall(VecConjugate(w)); 2809 PetscCall(MatMultTranspose(mat, w, y)); 2810 PetscCall(VecDestroy(&w)); 2811 PetscCall(VecConjugate(y)); 2812 } 2813 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2814 #else 2815 PetscCall(MatMultTranspose(mat, x, y)); 2816 #endif 2817 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2818 PetscFunctionReturn(PETSC_SUCCESS); 2819 } 2820 2821 /*@ 2822 MatMultAdd - Computes $v3 = v2 + A * v1$. 2823 2824 Neighbor-wise Collective 2825 2826 Input Parameters: 2827 + mat - the matrix 2828 . v1 - the vector to be multiplied by `mat` 2829 - v2 - the vector to be added to the result 2830 2831 Output Parameter: 2832 . v3 - the result 2833 2834 Level: beginner 2835 2836 Note: 2837 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2838 call `MatMultAdd`(A,v1,v2,v1). 2839 2840 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2841 @*/ 2842 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2843 { 2844 PetscFunctionBegin; 2845 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2846 PetscValidType(mat, 1); 2847 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2848 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2849 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2850 2851 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2852 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2853 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); 2854 /* 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); 2855 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); */ 2856 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); 2857 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); 2858 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2859 MatCheckPreallocated(mat, 1); 2860 2861 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2862 PetscCall(VecLockReadPush(v1)); 2863 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2864 PetscCall(VecLockReadPop(v1)); 2865 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2866 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2867 PetscFunctionReturn(PETSC_SUCCESS); 2868 } 2869 2870 /*@ 2871 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2872 2873 Neighbor-wise Collective 2874 2875 Input Parameters: 2876 + mat - the matrix 2877 . v1 - the vector to be multiplied by the transpose of the matrix 2878 - v2 - the vector to be added to the result 2879 2880 Output Parameter: 2881 . v3 - the result 2882 2883 Level: beginner 2884 2885 Note: 2886 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2887 call `MatMultTransposeAdd`(A,v1,v2,v1). 2888 2889 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2890 @*/ 2891 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2892 { 2893 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2894 2895 PetscFunctionBegin; 2896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2897 PetscValidType(mat, 1); 2898 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2899 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2900 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2901 2902 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2903 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2904 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); 2905 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); 2906 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); 2907 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2908 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2909 MatCheckPreallocated(mat, 1); 2910 2911 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2912 PetscCall(VecLockReadPush(v1)); 2913 PetscCall((*op)(mat, v1, v2, v3)); 2914 PetscCall(VecLockReadPop(v1)); 2915 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2916 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2917 PetscFunctionReturn(PETSC_SUCCESS); 2918 } 2919 2920 /*@ 2921 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2922 2923 Neighbor-wise Collective 2924 2925 Input Parameters: 2926 + mat - the matrix 2927 . v1 - the vector to be multiplied by the Hermitian transpose 2928 - v2 - the vector to be added to the result 2929 2930 Output Parameter: 2931 . v3 - the result 2932 2933 Level: beginner 2934 2935 Note: 2936 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2937 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2938 2939 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2940 @*/ 2941 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2942 { 2943 PetscFunctionBegin; 2944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2945 PetscValidType(mat, 1); 2946 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2947 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2948 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2949 2950 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2951 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2952 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2953 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); 2954 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); 2955 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); 2956 MatCheckPreallocated(mat, 1); 2957 2958 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2959 PetscCall(VecLockReadPush(v1)); 2960 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2961 else { 2962 Vec w, z; 2963 PetscCall(VecDuplicate(v1, &w)); 2964 PetscCall(VecCopy(v1, w)); 2965 PetscCall(VecConjugate(w)); 2966 PetscCall(VecDuplicate(v3, &z)); 2967 PetscCall(MatMultTranspose(mat, w, z)); 2968 PetscCall(VecDestroy(&w)); 2969 PetscCall(VecConjugate(z)); 2970 if (v2 != v3) { 2971 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2972 } else { 2973 PetscCall(VecAXPY(v3, 1.0, z)); 2974 } 2975 PetscCall(VecDestroy(&z)); 2976 } 2977 PetscCall(VecLockReadPop(v1)); 2978 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2979 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2980 PetscFunctionReturn(PETSC_SUCCESS); 2981 } 2982 2983 /*@ 2984 MatGetFactorType - gets the type of factorization a matrix is 2985 2986 Not Collective 2987 2988 Input Parameter: 2989 . mat - the matrix 2990 2991 Output Parameter: 2992 . 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` 2993 2994 Level: intermediate 2995 2996 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2997 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2998 @*/ 2999 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3000 { 3001 PetscFunctionBegin; 3002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3003 PetscValidType(mat, 1); 3004 PetscAssertPointer(t, 2); 3005 *t = mat->factortype; 3006 PetscFunctionReturn(PETSC_SUCCESS); 3007 } 3008 3009 /*@ 3010 MatSetFactorType - sets the type of factorization a matrix is 3011 3012 Logically Collective 3013 3014 Input Parameters: 3015 + mat - the matrix 3016 - 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` 3017 3018 Level: intermediate 3019 3020 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3021 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3022 @*/ 3023 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3024 { 3025 PetscFunctionBegin; 3026 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3027 PetscValidType(mat, 1); 3028 mat->factortype = t; 3029 PetscFunctionReturn(PETSC_SUCCESS); 3030 } 3031 3032 /*@ 3033 MatGetInfo - Returns information about matrix storage (number of 3034 nonzeros, memory, etc.). 3035 3036 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3037 3038 Input Parameters: 3039 + mat - the matrix 3040 - 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) 3041 3042 Output Parameter: 3043 . info - matrix information context 3044 3045 Options Database Key: 3046 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3047 3048 Level: intermediate 3049 3050 Notes: 3051 The `MatInfo` context contains a variety of matrix data, including 3052 number of nonzeros allocated and used, number of mallocs during 3053 matrix assembly, etc. Additional information for factored matrices 3054 is provided (such as the fill ratio, number of mallocs during 3055 factorization, etc.). 3056 3057 Example: 3058 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3059 data within the `MatInfo` context. For example, 3060 .vb 3061 MatInfo info; 3062 Mat A; 3063 double mal, nz_a, nz_u; 3064 3065 MatGetInfo(A, MAT_LOCAL, &info); 3066 mal = info.mallocs; 3067 nz_a = info.nz_allocated; 3068 .ve 3069 3070 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3071 @*/ 3072 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3073 { 3074 PetscFunctionBegin; 3075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3076 PetscValidType(mat, 1); 3077 PetscAssertPointer(info, 3); 3078 MatCheckPreallocated(mat, 1); 3079 PetscUseTypeMethod(mat, getinfo, flag, info); 3080 PetscFunctionReturn(PETSC_SUCCESS); 3081 } 3082 3083 /* 3084 This is used by external packages where it is not easy to get the info from the actual 3085 matrix factorization. 3086 */ 3087 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3088 { 3089 PetscFunctionBegin; 3090 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3091 PetscFunctionReturn(PETSC_SUCCESS); 3092 } 3093 3094 /*@ 3095 MatLUFactor - Performs in-place LU factorization of matrix. 3096 3097 Collective 3098 3099 Input Parameters: 3100 + mat - the matrix 3101 . row - row permutation 3102 . col - column permutation 3103 - info - options for factorization, includes 3104 .vb 3105 fill - expected fill as ratio of original fill. 3106 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3107 Run with the option -info to determine an optimal value to use 3108 .ve 3109 3110 Level: developer 3111 3112 Notes: 3113 Most users should employ the `KSP` interface for linear solvers 3114 instead of working directly with matrix algebra routines such as this. 3115 See, e.g., `KSPCreate()`. 3116 3117 This changes the state of the matrix to a factored matrix; it cannot be used 3118 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3119 3120 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3121 when not using `KSP`. 3122 3123 Fortran Note: 3124 A valid (non-null) `info` argument must be provided 3125 3126 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3127 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3128 @*/ 3129 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3130 { 3131 MatFactorInfo tinfo; 3132 3133 PetscFunctionBegin; 3134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3135 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3136 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3137 if (info) PetscAssertPointer(info, 4); 3138 PetscValidType(mat, 1); 3139 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3140 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3141 MatCheckPreallocated(mat, 1); 3142 if (!info) { 3143 PetscCall(MatFactorInfoInitialize(&tinfo)); 3144 info = &tinfo; 3145 } 3146 3147 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3148 PetscUseTypeMethod(mat, lufactor, row, col, info); 3149 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3150 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3151 PetscFunctionReturn(PETSC_SUCCESS); 3152 } 3153 3154 /*@ 3155 MatILUFactor - Performs in-place ILU factorization of matrix. 3156 3157 Collective 3158 3159 Input Parameters: 3160 + mat - the matrix 3161 . row - row permutation 3162 . col - column permutation 3163 - info - structure containing 3164 .vb 3165 levels - number of levels of fill. 3166 expected fill - as ratio of original fill. 3167 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3168 missing diagonal entries) 3169 .ve 3170 3171 Level: developer 3172 3173 Notes: 3174 Most users should employ the `KSP` interface for linear solvers 3175 instead of working directly with matrix algebra routines such as this. 3176 See, e.g., `KSPCreate()`. 3177 3178 Probably really in-place only when level of fill is zero, otherwise allocates 3179 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3180 when not using `KSP`. 3181 3182 Fortran Note: 3183 A valid (non-null) `info` argument must be provided 3184 3185 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3186 @*/ 3187 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3188 { 3189 PetscFunctionBegin; 3190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3191 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3192 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3193 PetscAssertPointer(info, 4); 3194 PetscValidType(mat, 1); 3195 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3196 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3197 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3198 MatCheckPreallocated(mat, 1); 3199 3200 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3201 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3202 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3203 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3204 PetscFunctionReturn(PETSC_SUCCESS); 3205 } 3206 3207 /*@ 3208 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3209 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3210 3211 Collective 3212 3213 Input Parameters: 3214 + fact - the factor matrix obtained with `MatGetFactor()` 3215 . mat - the matrix 3216 . row - the row permutation 3217 . col - the column permutation 3218 - info - options for factorization, includes 3219 .vb 3220 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3221 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3222 .ve 3223 3224 Level: developer 3225 3226 Notes: 3227 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3228 3229 Most users should employ the simplified `KSP` interface for linear solvers 3230 instead of working directly with matrix algebra routines such as this. 3231 See, e.g., `KSPCreate()`. 3232 3233 Fortran Note: 3234 A valid (non-null) `info` argument must be provided 3235 3236 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3237 @*/ 3238 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3239 { 3240 MatFactorInfo tinfo; 3241 3242 PetscFunctionBegin; 3243 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3245 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3246 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3247 if (info) PetscAssertPointer(info, 5); 3248 PetscValidType(fact, 1); 3249 PetscValidType(mat, 2); 3250 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3251 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3252 MatCheckPreallocated(mat, 2); 3253 if (!info) { 3254 PetscCall(MatFactorInfoInitialize(&tinfo)); 3255 info = &tinfo; 3256 } 3257 3258 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3259 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3260 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3261 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3262 PetscFunctionReturn(PETSC_SUCCESS); 3263 } 3264 3265 /*@ 3266 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3267 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3268 3269 Collective 3270 3271 Input Parameters: 3272 + fact - the factor matrix obtained with `MatGetFactor()` 3273 . mat - the matrix 3274 - info - options for factorization 3275 3276 Level: developer 3277 3278 Notes: 3279 See `MatLUFactor()` for in-place factorization. See 3280 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3281 3282 Most users should employ the `KSP` interface for linear solvers 3283 instead of working directly with matrix algebra routines such as this. 3284 See, e.g., `KSPCreate()`. 3285 3286 Fortran Note: 3287 A valid (non-null) `info` argument must be provided 3288 3289 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3290 @*/ 3291 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3292 { 3293 MatFactorInfo tinfo; 3294 3295 PetscFunctionBegin; 3296 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3297 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3298 PetscValidType(fact, 1); 3299 PetscValidType(mat, 2); 3300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3301 PetscCheck(mat->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, 3302 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3303 3304 MatCheckPreallocated(mat, 2); 3305 if (!info) { 3306 PetscCall(MatFactorInfoInitialize(&tinfo)); 3307 info = &tinfo; 3308 } 3309 3310 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3311 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3312 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3313 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3314 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3315 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3316 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3317 PetscFunctionReturn(PETSC_SUCCESS); 3318 } 3319 3320 /*@ 3321 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3322 symmetric matrix. 3323 3324 Collective 3325 3326 Input Parameters: 3327 + mat - the matrix 3328 . perm - row and column permutations 3329 - info - expected fill as ratio of original fill 3330 3331 Level: developer 3332 3333 Notes: 3334 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3335 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3336 3337 Most users should employ the `KSP` interface for linear solvers 3338 instead of working directly with matrix algebra routines such as this. 3339 See, e.g., `KSPCreate()`. 3340 3341 Fortran Note: 3342 A valid (non-null) `info` argument must be provided 3343 3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3345 `MatGetOrdering()` 3346 @*/ 3347 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3348 { 3349 MatFactorInfo tinfo; 3350 3351 PetscFunctionBegin; 3352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3353 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3354 if (info) PetscAssertPointer(info, 3); 3355 PetscValidType(mat, 1); 3356 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3357 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3358 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3359 MatCheckPreallocated(mat, 1); 3360 if (!info) { 3361 PetscCall(MatFactorInfoInitialize(&tinfo)); 3362 info = &tinfo; 3363 } 3364 3365 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3366 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3367 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3368 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3369 PetscFunctionReturn(PETSC_SUCCESS); 3370 } 3371 3372 /*@ 3373 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3374 of a symmetric matrix. 3375 3376 Collective 3377 3378 Input Parameters: 3379 + fact - the factor matrix obtained with `MatGetFactor()` 3380 . mat - the matrix 3381 . perm - row and column permutations 3382 - info - options for factorization, includes 3383 .vb 3384 fill - expected fill as ratio of original fill. 3385 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3386 Run with the option -info to determine an optimal value to use 3387 .ve 3388 3389 Level: developer 3390 3391 Notes: 3392 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3393 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3394 3395 Most users should employ the `KSP` interface for linear solvers 3396 instead of working directly with matrix algebra routines such as this. 3397 See, e.g., `KSPCreate()`. 3398 3399 Fortran Note: 3400 A valid (non-null) `info` argument must be provided 3401 3402 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3403 `MatGetOrdering()` 3404 @*/ 3405 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3406 { 3407 MatFactorInfo tinfo; 3408 3409 PetscFunctionBegin; 3410 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3411 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3412 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3413 if (info) PetscAssertPointer(info, 4); 3414 PetscValidType(fact, 1); 3415 PetscValidType(mat, 2); 3416 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3417 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3418 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3419 MatCheckPreallocated(mat, 2); 3420 if (!info) { 3421 PetscCall(MatFactorInfoInitialize(&tinfo)); 3422 info = &tinfo; 3423 } 3424 3425 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3426 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3427 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3428 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3429 PetscFunctionReturn(PETSC_SUCCESS); 3430 } 3431 3432 /*@ 3433 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3434 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3435 `MatCholeskyFactorSymbolic()`. 3436 3437 Collective 3438 3439 Input Parameters: 3440 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3441 . mat - the initial matrix that is to be factored 3442 - info - options for factorization 3443 3444 Level: developer 3445 3446 Note: 3447 Most users should employ the `KSP` interface for linear solvers 3448 instead of working directly with matrix algebra routines such as this. 3449 See, e.g., `KSPCreate()`. 3450 3451 Fortran Note: 3452 A valid (non-null) `info` argument must be provided 3453 3454 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3455 @*/ 3456 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3457 { 3458 MatFactorInfo tinfo; 3459 3460 PetscFunctionBegin; 3461 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3463 PetscValidType(fact, 1); 3464 PetscValidType(mat, 2); 3465 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3466 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, 3467 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3468 MatCheckPreallocated(mat, 2); 3469 if (!info) { 3470 PetscCall(MatFactorInfoInitialize(&tinfo)); 3471 info = &tinfo; 3472 } 3473 3474 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3475 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3476 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3477 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3478 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3479 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3480 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3481 PetscFunctionReturn(PETSC_SUCCESS); 3482 } 3483 3484 /*@ 3485 MatQRFactor - Performs in-place QR factorization of matrix. 3486 3487 Collective 3488 3489 Input Parameters: 3490 + mat - the matrix 3491 . col - column permutation 3492 - info - options for factorization, includes 3493 .vb 3494 fill - expected fill as ratio of original fill. 3495 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3496 Run with the option -info to determine an optimal value to use 3497 .ve 3498 3499 Level: developer 3500 3501 Notes: 3502 Most users should employ the `KSP` interface for linear solvers 3503 instead of working directly with matrix algebra routines such as this. 3504 See, e.g., `KSPCreate()`. 3505 3506 This changes the state of the matrix to a factored matrix; it cannot be used 3507 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3508 3509 Fortran Note: 3510 A valid (non-null) `info` argument must be provided 3511 3512 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3513 `MatSetUnfactored()` 3514 @*/ 3515 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3516 { 3517 PetscFunctionBegin; 3518 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3519 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3520 if (info) PetscAssertPointer(info, 3); 3521 PetscValidType(mat, 1); 3522 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3523 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3524 MatCheckPreallocated(mat, 1); 3525 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3526 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3527 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3528 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3529 PetscFunctionReturn(PETSC_SUCCESS); 3530 } 3531 3532 /*@ 3533 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3534 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3535 3536 Collective 3537 3538 Input Parameters: 3539 + fact - the factor matrix obtained with `MatGetFactor()` 3540 . mat - the matrix 3541 . col - column permutation 3542 - info - options for factorization, includes 3543 .vb 3544 fill - expected fill as ratio of original fill. 3545 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3546 Run with the option -info to determine an optimal value to use 3547 .ve 3548 3549 Level: developer 3550 3551 Note: 3552 Most users should employ the `KSP` interface for linear solvers 3553 instead of working directly with matrix algebra routines such as this. 3554 See, e.g., `KSPCreate()`. 3555 3556 Fortran Note: 3557 A valid (non-null) `info` argument must be provided 3558 3559 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3560 @*/ 3561 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3562 { 3563 MatFactorInfo tinfo; 3564 3565 PetscFunctionBegin; 3566 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3568 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3569 if (info) PetscAssertPointer(info, 4); 3570 PetscValidType(fact, 1); 3571 PetscValidType(mat, 2); 3572 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3573 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3574 MatCheckPreallocated(mat, 2); 3575 if (!info) { 3576 PetscCall(MatFactorInfoInitialize(&tinfo)); 3577 info = &tinfo; 3578 } 3579 3580 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3581 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3582 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3583 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3584 PetscFunctionReturn(PETSC_SUCCESS); 3585 } 3586 3587 /*@ 3588 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3589 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3590 3591 Collective 3592 3593 Input Parameters: 3594 + fact - the factor matrix obtained with `MatGetFactor()` 3595 . mat - the matrix 3596 - info - options for factorization 3597 3598 Level: developer 3599 3600 Notes: 3601 See `MatQRFactor()` for in-place factorization. 3602 3603 Most users should employ the `KSP` interface for linear solvers 3604 instead of working directly with matrix algebra routines such as this. 3605 See, e.g., `KSPCreate()`. 3606 3607 Fortran Note: 3608 A valid (non-null) `info` argument must be provided 3609 3610 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3611 @*/ 3612 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3613 { 3614 MatFactorInfo tinfo; 3615 3616 PetscFunctionBegin; 3617 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3619 PetscValidType(fact, 1); 3620 PetscValidType(mat, 2); 3621 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3622 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, 3623 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3624 3625 MatCheckPreallocated(mat, 2); 3626 if (!info) { 3627 PetscCall(MatFactorInfoInitialize(&tinfo)); 3628 info = &tinfo; 3629 } 3630 3631 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3632 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3633 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3634 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3635 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3636 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3637 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 3641 /*@ 3642 MatSolve - Solves $A x = b$, given a factored matrix. 3643 3644 Neighbor-wise Collective 3645 3646 Input Parameters: 3647 + mat - the factored matrix 3648 - b - the right-hand-side vector 3649 3650 Output Parameter: 3651 . x - the result vector 3652 3653 Level: developer 3654 3655 Notes: 3656 The vectors `b` and `x` cannot be the same. I.e., one cannot 3657 call `MatSolve`(A,x,x). 3658 3659 Most users should employ the `KSP` interface for linear solvers 3660 instead of working directly with matrix algebra routines such as this. 3661 See, e.g., `KSPCreate()`. 3662 3663 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3664 @*/ 3665 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3666 { 3667 PetscFunctionBegin; 3668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3669 PetscValidType(mat, 1); 3670 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3671 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3672 PetscCheckSameComm(mat, 1, b, 2); 3673 PetscCheckSameComm(mat, 1, x, 3); 3674 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3675 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); 3676 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); 3677 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); 3678 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3679 MatCheckPreallocated(mat, 1); 3680 3681 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3682 PetscCall(VecFlag(x, mat->factorerrortype)); 3683 if (mat->factorerrortype) { 3684 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3685 } else PetscUseTypeMethod(mat, solve, b, x); 3686 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3687 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3688 PetscFunctionReturn(PETSC_SUCCESS); 3689 } 3690 3691 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3692 { 3693 Vec b, x; 3694 PetscInt N, i; 3695 PetscErrorCode (*f)(Mat, Vec, Vec); 3696 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3697 3698 PetscFunctionBegin; 3699 if (A->factorerrortype) { 3700 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3701 PetscCall(MatSetInf(X)); 3702 PetscFunctionReturn(PETSC_SUCCESS); 3703 } 3704 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3705 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3706 PetscCall(MatBoundToCPU(A, &Abound)); 3707 if (!Abound) { 3708 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3709 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3710 } 3711 #if PetscDefined(HAVE_CUDA) 3712 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3713 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3714 #elif PetscDefined(HAVE_HIP) 3715 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3716 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3717 #endif 3718 PetscCall(MatGetSize(B, NULL, &N)); 3719 for (i = 0; i < N; i++) { 3720 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3721 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3722 PetscCall((*f)(A, b, x)); 3723 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3724 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3725 } 3726 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3727 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3728 PetscFunctionReturn(PETSC_SUCCESS); 3729 } 3730 3731 /*@ 3732 MatMatSolve - Solves $A X = B$, given a factored matrix. 3733 3734 Neighbor-wise Collective 3735 3736 Input Parameters: 3737 + A - the factored matrix 3738 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3739 3740 Output Parameter: 3741 . X - the result matrix (dense matrix) 3742 3743 Level: developer 3744 3745 Note: 3746 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3747 otherwise, `B` and `X` cannot be the same. 3748 3749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3750 @*/ 3751 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3752 { 3753 PetscFunctionBegin; 3754 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3755 PetscValidType(A, 1); 3756 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3757 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3758 PetscCheckSameComm(A, 1, B, 2); 3759 PetscCheckSameComm(A, 1, X, 3); 3760 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); 3761 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); 3762 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"); 3763 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3764 MatCheckPreallocated(A, 1); 3765 3766 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3767 if (!A->ops->matsolve) { 3768 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3769 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3770 } else PetscUseTypeMethod(A, matsolve, B, X); 3771 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3772 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3773 PetscFunctionReturn(PETSC_SUCCESS); 3774 } 3775 3776 /*@ 3777 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3778 3779 Neighbor-wise Collective 3780 3781 Input Parameters: 3782 + A - the factored matrix 3783 - B - the right-hand-side matrix (`MATDENSE` matrix) 3784 3785 Output Parameter: 3786 . X - the result matrix (dense matrix) 3787 3788 Level: developer 3789 3790 Note: 3791 The matrices `B` and `X` cannot be the same. I.e., one cannot 3792 call `MatMatSolveTranspose`(A,X,X). 3793 3794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3795 @*/ 3796 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3797 { 3798 PetscFunctionBegin; 3799 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3800 PetscValidType(A, 1); 3801 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3802 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3803 PetscCheckSameComm(A, 1, B, 2); 3804 PetscCheckSameComm(A, 1, X, 3); 3805 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3806 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); 3807 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); 3808 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); 3809 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"); 3810 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3811 MatCheckPreallocated(A, 1); 3812 3813 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3814 if (!A->ops->matsolvetranspose) { 3815 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3816 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3817 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3818 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3819 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3820 PetscFunctionReturn(PETSC_SUCCESS); 3821 } 3822 3823 /*@ 3824 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3825 3826 Neighbor-wise Collective 3827 3828 Input Parameters: 3829 + A - the factored matrix 3830 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3831 3832 Output Parameter: 3833 . X - the result matrix (dense matrix) 3834 3835 Level: developer 3836 3837 Note: 3838 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 3839 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3840 3841 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3842 @*/ 3843 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3844 { 3845 PetscFunctionBegin; 3846 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3847 PetscValidType(A, 1); 3848 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3849 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3850 PetscCheckSameComm(A, 1, Bt, 2); 3851 PetscCheckSameComm(A, 1, X, 3); 3852 3853 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3854 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); 3855 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); 3856 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"); 3857 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3858 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3859 MatCheckPreallocated(A, 1); 3860 3861 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3862 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3863 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3864 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3865 PetscFunctionReturn(PETSC_SUCCESS); 3866 } 3867 3868 /*@ 3869 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3870 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3871 3872 Neighbor-wise Collective 3873 3874 Input Parameters: 3875 + mat - the factored matrix 3876 - b - the right-hand-side vector 3877 3878 Output Parameter: 3879 . x - the result vector 3880 3881 Level: developer 3882 3883 Notes: 3884 `MatSolve()` should be used for most applications, as it performs 3885 a forward solve followed by a backward solve. 3886 3887 The vectors `b` and `x` cannot be the same, i.e., one cannot 3888 call `MatForwardSolve`(A,x,x). 3889 3890 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3891 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3892 `MatForwardSolve()` solves $U^T*D y = b$, and 3893 `MatBackwardSolve()` solves $U x = y$. 3894 Thus they do not provide a symmetric preconditioner. 3895 3896 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3897 @*/ 3898 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3899 { 3900 PetscFunctionBegin; 3901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3902 PetscValidType(mat, 1); 3903 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3904 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3905 PetscCheckSameComm(mat, 1, b, 2); 3906 PetscCheckSameComm(mat, 1, x, 3); 3907 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3908 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); 3909 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); 3910 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); 3911 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3912 MatCheckPreallocated(mat, 1); 3913 3914 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3915 PetscUseTypeMethod(mat, forwardsolve, b, x); 3916 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3917 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3918 PetscFunctionReturn(PETSC_SUCCESS); 3919 } 3920 3921 /*@ 3922 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3923 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3924 3925 Neighbor-wise Collective 3926 3927 Input Parameters: 3928 + mat - the factored matrix 3929 - b - the right-hand-side vector 3930 3931 Output Parameter: 3932 . x - the result vector 3933 3934 Level: developer 3935 3936 Notes: 3937 `MatSolve()` should be used for most applications, as it performs 3938 a forward solve followed by a backward solve. 3939 3940 The vectors `b` and `x` cannot be the same. I.e., one cannot 3941 call `MatBackwardSolve`(A,x,x). 3942 3943 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3944 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3945 `MatForwardSolve()` solves $U^T*D y = b$, and 3946 `MatBackwardSolve()` solves $U x = y$. 3947 Thus they do not provide a symmetric preconditioner. 3948 3949 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3950 @*/ 3951 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3952 { 3953 PetscFunctionBegin; 3954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3955 PetscValidType(mat, 1); 3956 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3957 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3958 PetscCheckSameComm(mat, 1, b, 2); 3959 PetscCheckSameComm(mat, 1, x, 3); 3960 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3961 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); 3962 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); 3963 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); 3964 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3965 MatCheckPreallocated(mat, 1); 3966 3967 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3968 PetscUseTypeMethod(mat, backwardsolve, b, x); 3969 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3970 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3971 PetscFunctionReturn(PETSC_SUCCESS); 3972 } 3973 3974 /*@ 3975 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3976 3977 Neighbor-wise Collective 3978 3979 Input Parameters: 3980 + mat - the factored matrix 3981 . b - the right-hand-side vector 3982 - y - the vector to be added to 3983 3984 Output Parameter: 3985 . x - the result vector 3986 3987 Level: developer 3988 3989 Note: 3990 The vectors `b` and `x` cannot be the same. I.e., one cannot 3991 call `MatSolveAdd`(A,x,y,x). 3992 3993 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3994 @*/ 3995 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3996 { 3997 PetscScalar one = 1.0; 3998 Vec tmp; 3999 4000 PetscFunctionBegin; 4001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4002 PetscValidType(mat, 1); 4003 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4004 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4005 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4006 PetscCheckSameComm(mat, 1, b, 2); 4007 PetscCheckSameComm(mat, 1, y, 3); 4008 PetscCheckSameComm(mat, 1, x, 4); 4009 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4010 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); 4011 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); 4012 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); 4013 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); 4014 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); 4015 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4016 MatCheckPreallocated(mat, 1); 4017 4018 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4019 PetscCall(VecFlag(x, mat->factorerrortype)); 4020 if (mat->factorerrortype) { 4021 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4022 } else if (mat->ops->solveadd) { 4023 PetscUseTypeMethod(mat, solveadd, b, y, x); 4024 } else { 4025 /* do the solve then the add manually */ 4026 if (x != y) { 4027 PetscCall(MatSolve(mat, b, x)); 4028 PetscCall(VecAXPY(x, one, y)); 4029 } else { 4030 PetscCall(VecDuplicate(x, &tmp)); 4031 PetscCall(VecCopy(x, tmp)); 4032 PetscCall(MatSolve(mat, b, x)); 4033 PetscCall(VecAXPY(x, one, tmp)); 4034 PetscCall(VecDestroy(&tmp)); 4035 } 4036 } 4037 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4038 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4039 PetscFunctionReturn(PETSC_SUCCESS); 4040 } 4041 4042 /*@ 4043 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4044 4045 Neighbor-wise Collective 4046 4047 Input Parameters: 4048 + mat - the factored matrix 4049 - b - the right-hand-side vector 4050 4051 Output Parameter: 4052 . x - the result vector 4053 4054 Level: developer 4055 4056 Notes: 4057 The vectors `b` and `x` cannot be the same. I.e., one cannot 4058 call `MatSolveTranspose`(A,x,x). 4059 4060 Most users should employ the `KSP` interface for linear solvers 4061 instead of working directly with matrix algebra routines such as this. 4062 See, e.g., `KSPCreate()`. 4063 4064 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4065 @*/ 4066 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4067 { 4068 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4069 4070 PetscFunctionBegin; 4071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4072 PetscValidType(mat, 1); 4073 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4074 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4075 PetscCheckSameComm(mat, 1, b, 2); 4076 PetscCheckSameComm(mat, 1, x, 3); 4077 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4078 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); 4079 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); 4080 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4081 MatCheckPreallocated(mat, 1); 4082 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4083 PetscCall(VecFlag(x, mat->factorerrortype)); 4084 if (mat->factorerrortype) { 4085 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4086 } else { 4087 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4088 PetscCall((*f)(mat, b, x)); 4089 } 4090 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4091 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4092 PetscFunctionReturn(PETSC_SUCCESS); 4093 } 4094 4095 /*@ 4096 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4097 factored matrix. 4098 4099 Neighbor-wise Collective 4100 4101 Input Parameters: 4102 + mat - the factored matrix 4103 . b - the right-hand-side vector 4104 - y - the vector to be added to 4105 4106 Output Parameter: 4107 . x - the result vector 4108 4109 Level: developer 4110 4111 Note: 4112 The vectors `b` and `x` cannot be the same. I.e., one cannot 4113 call `MatSolveTransposeAdd`(A,x,y,x). 4114 4115 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4116 @*/ 4117 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4118 { 4119 PetscScalar one = 1.0; 4120 Vec tmp; 4121 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4122 4123 PetscFunctionBegin; 4124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4125 PetscValidType(mat, 1); 4126 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4127 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4128 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4129 PetscCheckSameComm(mat, 1, b, 2); 4130 PetscCheckSameComm(mat, 1, y, 3); 4131 PetscCheckSameComm(mat, 1, x, 4); 4132 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4133 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); 4134 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); 4135 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); 4136 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); 4137 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4138 MatCheckPreallocated(mat, 1); 4139 4140 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4141 PetscCall(VecFlag(x, mat->factorerrortype)); 4142 if (mat->factorerrortype) { 4143 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4144 } else if (f) { 4145 PetscCall((*f)(mat, b, y, x)); 4146 } else { 4147 /* do the solve then the add manually */ 4148 if (x != y) { 4149 PetscCall(MatSolveTranspose(mat, b, x)); 4150 PetscCall(VecAXPY(x, one, y)); 4151 } else { 4152 PetscCall(VecDuplicate(x, &tmp)); 4153 PetscCall(VecCopy(x, tmp)); 4154 PetscCall(MatSolveTranspose(mat, b, x)); 4155 PetscCall(VecAXPY(x, one, tmp)); 4156 PetscCall(VecDestroy(&tmp)); 4157 } 4158 } 4159 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4160 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4161 PetscFunctionReturn(PETSC_SUCCESS); 4162 } 4163 4164 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4165 /*@ 4166 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4167 4168 Neighbor-wise Collective 4169 4170 Input Parameters: 4171 + mat - the matrix 4172 . b - the right-hand side 4173 . omega - the relaxation factor 4174 . flag - flag indicating the type of SOR (see below) 4175 . shift - diagonal shift 4176 . its - the number of iterations 4177 - lits - the number of local iterations 4178 4179 Output Parameter: 4180 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4181 4182 SOR Flags: 4183 + `SOR_FORWARD_SWEEP` - forward SOR 4184 . `SOR_BACKWARD_SWEEP` - backward SOR 4185 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4186 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4187 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4188 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4189 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4190 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4191 upper/lower triangular part of matrix to 4192 vector (with omega) 4193 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4194 4195 Level: developer 4196 4197 Notes: 4198 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4199 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4200 on each processor. 4201 4202 Application programmers will not generally use `MatSOR()` directly, 4203 but instead will employ the `KSP`/`PC` interface. 4204 4205 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4206 4207 Most users should employ the `KSP` interface for linear solvers 4208 instead of working directly with matrix algebra routines such as this. 4209 See, e.g., `KSPCreate()`. 4210 4211 Vectors `x` and `b` CANNOT be the same 4212 4213 The flags are implemented as bitwise inclusive or operations. 4214 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4215 to specify a zero initial guess for SSOR. 4216 4217 Developer Note: 4218 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4219 4220 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4221 @*/ 4222 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4223 { 4224 PetscFunctionBegin; 4225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4226 PetscValidType(mat, 1); 4227 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4228 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4229 PetscCheckSameComm(mat, 1, b, 2); 4230 PetscCheckSameComm(mat, 1, x, 8); 4231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4232 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4233 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); 4234 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); 4235 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); 4236 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4237 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4238 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4239 4240 MatCheckPreallocated(mat, 1); 4241 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4242 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4243 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4244 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4245 PetscFunctionReturn(PETSC_SUCCESS); 4246 } 4247 4248 /* 4249 Default matrix copy routine. 4250 */ 4251 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4252 { 4253 PetscInt i, rstart = 0, rend = 0, nz; 4254 const PetscInt *cwork; 4255 const PetscScalar *vwork; 4256 4257 PetscFunctionBegin; 4258 if (B->assembled) PetscCall(MatZeroEntries(B)); 4259 if (str == SAME_NONZERO_PATTERN) { 4260 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4261 for (i = rstart; i < rend; i++) { 4262 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4263 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4264 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4265 } 4266 } else { 4267 PetscCall(MatAYPX(B, 0.0, A, str)); 4268 } 4269 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4270 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4271 PetscFunctionReturn(PETSC_SUCCESS); 4272 } 4273 4274 /*@ 4275 MatCopy - Copies a matrix to another matrix. 4276 4277 Collective 4278 4279 Input Parameters: 4280 + A - the matrix 4281 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4282 4283 Output Parameter: 4284 . B - where the copy is put 4285 4286 Level: intermediate 4287 4288 Notes: 4289 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4290 4291 `MatCopy()` copies the matrix entries of a matrix to another existing 4292 matrix (after first zeroing the second matrix). A related routine is 4293 `MatConvert()`, which first creates a new matrix and then copies the data. 4294 4295 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4296 @*/ 4297 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4298 { 4299 PetscInt i; 4300 4301 PetscFunctionBegin; 4302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4303 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4304 PetscValidType(A, 1); 4305 PetscValidType(B, 2); 4306 PetscCheckSameComm(A, 1, B, 2); 4307 MatCheckPreallocated(B, 2); 4308 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4309 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4310 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, 4311 A->cmap->N, B->cmap->N); 4312 MatCheckPreallocated(A, 1); 4313 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4314 4315 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4316 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4317 else PetscCall(MatCopy_Basic(A, B, str)); 4318 4319 B->stencil.dim = A->stencil.dim; 4320 B->stencil.noc = A->stencil.noc; 4321 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4322 B->stencil.dims[i] = A->stencil.dims[i]; 4323 B->stencil.starts[i] = A->stencil.starts[i]; 4324 } 4325 4326 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4327 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4328 PetscFunctionReturn(PETSC_SUCCESS); 4329 } 4330 4331 /*@ 4332 MatConvert - Converts a matrix to another matrix, either of the same 4333 or different type. 4334 4335 Collective 4336 4337 Input Parameters: 4338 + mat - the matrix 4339 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4340 same type as the original matrix. 4341 - reuse - denotes if the destination matrix is to be created or reused. 4342 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 4343 `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). 4344 4345 Output Parameter: 4346 . M - pointer to place new matrix 4347 4348 Level: intermediate 4349 4350 Notes: 4351 `MatConvert()` first creates a new matrix and then copies the data from 4352 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4353 entries of one matrix to another already existing matrix context. 4354 4355 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4356 the MPI communicator of the generated matrix is always the same as the communicator 4357 of the input matrix. 4358 4359 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4360 @*/ 4361 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4362 { 4363 PetscBool sametype, issame, flg; 4364 PetscBool3 issymmetric, ishermitian; 4365 char convname[256], mtype[256]; 4366 Mat B; 4367 4368 PetscFunctionBegin; 4369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4370 PetscValidType(mat, 1); 4371 PetscAssertPointer(M, 4); 4372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4373 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4374 MatCheckPreallocated(mat, 1); 4375 4376 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4377 if (flg) newtype = mtype; 4378 4379 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4380 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4381 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4382 if (reuse == MAT_REUSE_MATRIX) { 4383 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4384 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4385 } 4386 4387 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4388 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4389 PetscFunctionReturn(PETSC_SUCCESS); 4390 } 4391 4392 /* Cache Mat options because some converters use MatHeaderReplace */ 4393 issymmetric = mat->symmetric; 4394 ishermitian = mat->hermitian; 4395 4396 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4397 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4398 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4399 } else { 4400 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4401 const char *prefix[3] = {"seq", "mpi", ""}; 4402 PetscInt i; 4403 /* 4404 Order of precedence: 4405 0) See if newtype is a superclass of the current matrix. 4406 1) See if a specialized converter is known to the current matrix. 4407 2) See if a specialized converter is known to the desired matrix class. 4408 3) See if a good general converter is registered for the desired class 4409 (as of 6/27/03 only MATMPIADJ falls into this category). 4410 4) See if a good general converter is known for the current matrix. 4411 5) Use a really basic converter. 4412 */ 4413 4414 /* 0) See if newtype is a superclass of the current matrix. 4415 i.e mat is mpiaij and newtype is aij */ 4416 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4417 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4418 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4419 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4420 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4421 if (flg) { 4422 if (reuse == MAT_INPLACE_MATRIX) { 4423 PetscCall(PetscInfo(mat, "Early return\n")); 4424 PetscFunctionReturn(PETSC_SUCCESS); 4425 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4426 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4427 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4428 PetscFunctionReturn(PETSC_SUCCESS); 4429 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4430 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4431 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4432 PetscFunctionReturn(PETSC_SUCCESS); 4433 } 4434 } 4435 } 4436 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4437 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4438 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4439 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4440 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4441 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4443 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4444 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4445 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4446 if (conv) goto foundconv; 4447 } 4448 4449 /* 2) See if a specialized converter is known to the desired matrix class. */ 4450 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4451 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4452 PetscCall(MatSetType(B, newtype)); 4453 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4454 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4455 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4456 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4457 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4458 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4459 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4460 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4461 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4462 if (conv) { 4463 PetscCall(MatDestroy(&B)); 4464 goto foundconv; 4465 } 4466 } 4467 4468 /* 3) See if a good general converter is registered for the desired class */ 4469 conv = B->ops->convertfrom; 4470 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4471 PetscCall(MatDestroy(&B)); 4472 if (conv) goto foundconv; 4473 4474 /* 4) See if a good general converter is known for the current matrix */ 4475 if (mat->ops->convert) conv = mat->ops->convert; 4476 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4477 if (conv) goto foundconv; 4478 4479 /* 5) Use a really basic converter. */ 4480 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4481 conv = MatConvert_Basic; 4482 4483 foundconv: 4484 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4485 PetscCall((*conv)(mat, newtype, reuse, M)); 4486 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4487 /* the block sizes must be same if the mappings are copied over */ 4488 (*M)->rmap->bs = mat->rmap->bs; 4489 (*M)->cmap->bs = mat->cmap->bs; 4490 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4491 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4492 (*M)->rmap->mapping = mat->rmap->mapping; 4493 (*M)->cmap->mapping = mat->cmap->mapping; 4494 } 4495 (*M)->stencil.dim = mat->stencil.dim; 4496 (*M)->stencil.noc = mat->stencil.noc; 4497 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4498 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4499 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4500 } 4501 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4502 } 4503 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4504 4505 /* Copy Mat options */ 4506 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4507 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4508 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4509 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4510 PetscFunctionReturn(PETSC_SUCCESS); 4511 } 4512 4513 /*@ 4514 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4515 4516 Not Collective 4517 4518 Input Parameter: 4519 . mat - the matrix, must be a factored matrix 4520 4521 Output Parameter: 4522 . type - the string name of the package (do not free this string) 4523 4524 Level: intermediate 4525 4526 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4527 @*/ 4528 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4529 { 4530 PetscErrorCode (*conv)(Mat, MatSolverType *); 4531 4532 PetscFunctionBegin; 4533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4534 PetscValidType(mat, 1); 4535 PetscAssertPointer(type, 2); 4536 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4537 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4538 if (conv) PetscCall((*conv)(mat, type)); 4539 else *type = MATSOLVERPETSC; 4540 PetscFunctionReturn(PETSC_SUCCESS); 4541 } 4542 4543 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4544 struct _MatSolverTypeForSpecifcType { 4545 MatType mtype; 4546 /* no entry for MAT_FACTOR_NONE */ 4547 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4548 MatSolverTypeForSpecifcType next; 4549 }; 4550 4551 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4552 struct _MatSolverTypeHolder { 4553 char *name; 4554 MatSolverTypeForSpecifcType handlers; 4555 MatSolverTypeHolder next; 4556 }; 4557 4558 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4559 4560 /*@C 4561 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4562 4563 Logically Collective, No Fortran Support 4564 4565 Input Parameters: 4566 + package - name of the package, for example `petsc` or `superlu` 4567 . mtype - the matrix type that works with this package 4568 . ftype - the type of factorization supported by the package 4569 - createfactor - routine that will create the factored matrix ready to be used 4570 4571 Level: developer 4572 4573 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4574 `MatGetFactor()` 4575 @*/ 4576 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4577 { 4578 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4579 PetscBool flg; 4580 MatSolverTypeForSpecifcType inext, iprev = NULL; 4581 4582 PetscFunctionBegin; 4583 PetscCall(MatInitializePackage()); 4584 if (!next) { 4585 PetscCall(PetscNew(&MatSolverTypeHolders)); 4586 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4587 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4588 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4589 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4590 PetscFunctionReturn(PETSC_SUCCESS); 4591 } 4592 while (next) { 4593 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4594 if (flg) { 4595 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4596 inext = next->handlers; 4597 while (inext) { 4598 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4599 if (flg) { 4600 inext->createfactor[(int)ftype - 1] = createfactor; 4601 PetscFunctionReturn(PETSC_SUCCESS); 4602 } 4603 iprev = inext; 4604 inext = inext->next; 4605 } 4606 PetscCall(PetscNew(&iprev->next)); 4607 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4608 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4609 PetscFunctionReturn(PETSC_SUCCESS); 4610 } 4611 prev = next; 4612 next = next->next; 4613 } 4614 PetscCall(PetscNew(&prev->next)); 4615 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4616 PetscCall(PetscNew(&prev->next->handlers)); 4617 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4618 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4619 PetscFunctionReturn(PETSC_SUCCESS); 4620 } 4621 4622 /*@C 4623 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4624 4625 Input Parameters: 4626 + 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 4627 . ftype - the type of factorization supported by the type 4628 - mtype - the matrix type that works with this type 4629 4630 Output Parameters: 4631 + foundtype - `PETSC_TRUE` if the type was registered 4632 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4633 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4634 4635 Calling sequence of `createfactor`: 4636 + A - the matrix providing the factor matrix 4637 . ftype - the `MatFactorType` of the factor requested 4638 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4639 4640 Level: developer 4641 4642 Note: 4643 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4644 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4645 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4646 4647 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4648 `MatInitializePackage()` 4649 @*/ 4650 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4651 { 4652 MatSolverTypeHolder next = MatSolverTypeHolders; 4653 PetscBool flg; 4654 MatSolverTypeForSpecifcType inext; 4655 4656 PetscFunctionBegin; 4657 if (foundtype) *foundtype = PETSC_FALSE; 4658 if (foundmtype) *foundmtype = PETSC_FALSE; 4659 if (createfactor) *createfactor = NULL; 4660 4661 if (type) { 4662 while (next) { 4663 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4664 if (flg) { 4665 if (foundtype) *foundtype = PETSC_TRUE; 4666 inext = next->handlers; 4667 while (inext) { 4668 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4669 if (flg) { 4670 if (foundmtype) *foundmtype = PETSC_TRUE; 4671 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4672 PetscFunctionReturn(PETSC_SUCCESS); 4673 } 4674 inext = inext->next; 4675 } 4676 } 4677 next = next->next; 4678 } 4679 } else { 4680 while (next) { 4681 inext = next->handlers; 4682 while (inext) { 4683 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4684 if (flg && inext->createfactor[(int)ftype - 1]) { 4685 if (foundtype) *foundtype = PETSC_TRUE; 4686 if (foundmtype) *foundmtype = PETSC_TRUE; 4687 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4688 PetscFunctionReturn(PETSC_SUCCESS); 4689 } 4690 inext = inext->next; 4691 } 4692 next = next->next; 4693 } 4694 /* try with base classes inext->mtype */ 4695 next = MatSolverTypeHolders; 4696 while (next) { 4697 inext = next->handlers; 4698 while (inext) { 4699 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4700 if (flg && inext->createfactor[(int)ftype - 1]) { 4701 if (foundtype) *foundtype = PETSC_TRUE; 4702 if (foundmtype) *foundmtype = PETSC_TRUE; 4703 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4704 PetscFunctionReturn(PETSC_SUCCESS); 4705 } 4706 inext = inext->next; 4707 } 4708 next = next->next; 4709 } 4710 } 4711 PetscFunctionReturn(PETSC_SUCCESS); 4712 } 4713 4714 PetscErrorCode MatSolverTypeDestroy(void) 4715 { 4716 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4717 MatSolverTypeForSpecifcType inext, iprev; 4718 4719 PetscFunctionBegin; 4720 while (next) { 4721 PetscCall(PetscFree(next->name)); 4722 inext = next->handlers; 4723 while (inext) { 4724 PetscCall(PetscFree(inext->mtype)); 4725 iprev = inext; 4726 inext = inext->next; 4727 PetscCall(PetscFree(iprev)); 4728 } 4729 prev = next; 4730 next = next->next; 4731 PetscCall(PetscFree(prev)); 4732 } 4733 MatSolverTypeHolders = NULL; 4734 PetscFunctionReturn(PETSC_SUCCESS); 4735 } 4736 4737 /*@ 4738 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4739 4740 Logically Collective 4741 4742 Input Parameter: 4743 . mat - the matrix 4744 4745 Output Parameter: 4746 . flg - `PETSC_TRUE` if uses the ordering 4747 4748 Level: developer 4749 4750 Note: 4751 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4752 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4753 4754 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4755 @*/ 4756 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4757 { 4758 PetscFunctionBegin; 4759 *flg = mat->canuseordering; 4760 PetscFunctionReturn(PETSC_SUCCESS); 4761 } 4762 4763 /*@ 4764 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4765 4766 Logically Collective 4767 4768 Input Parameters: 4769 + mat - the matrix obtained with `MatGetFactor()` 4770 - ftype - the factorization type to be used 4771 4772 Output Parameter: 4773 . otype - the preferred ordering type 4774 4775 Level: developer 4776 4777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4778 @*/ 4779 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4780 { 4781 PetscFunctionBegin; 4782 *otype = mat->preferredordering[ftype]; 4783 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4784 PetscFunctionReturn(PETSC_SUCCESS); 4785 } 4786 4787 /*@ 4788 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4789 4790 Collective 4791 4792 Input Parameters: 4793 + mat - the matrix 4794 . 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 4795 the other criteria is returned 4796 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4797 4798 Output Parameter: 4799 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4800 4801 Options Database Keys: 4802 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4803 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4804 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4805 4806 Level: intermediate 4807 4808 Notes: 4809 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4810 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4811 4812 Users usually access the factorization solvers via `KSP` 4813 4814 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4815 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 4816 4817 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4818 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4819 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4820 4821 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4822 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4823 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4824 4825 Developer Note: 4826 This should actually be called `MatCreateFactor()` since it creates a new factor object 4827 4828 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4829 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4830 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4831 @*/ 4832 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4833 { 4834 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4835 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4836 4837 PetscFunctionBegin; 4838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4839 PetscValidType(mat, 1); 4840 4841 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4842 MatCheckPreallocated(mat, 1); 4843 4844 PetscCall(MatIsShell(mat, &shell)); 4845 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4846 if (hasop) { 4847 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4848 PetscFunctionReturn(PETSC_SUCCESS); 4849 } 4850 4851 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4852 if (!foundtype) { 4853 if (type) { 4854 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], 4855 ((PetscObject)mat)->type_name, type); 4856 } else { 4857 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); 4858 } 4859 } 4860 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4861 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); 4862 4863 PetscCall((*conv)(mat, ftype, f)); 4864 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4865 PetscFunctionReturn(PETSC_SUCCESS); 4866 } 4867 4868 /*@ 4869 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4870 4871 Not Collective 4872 4873 Input Parameters: 4874 + mat - the matrix 4875 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4876 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4877 4878 Output Parameter: 4879 . flg - PETSC_TRUE if the factorization is available 4880 4881 Level: intermediate 4882 4883 Notes: 4884 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4885 such as pastix, superlu, mumps etc. 4886 4887 PETSc must have been ./configure to use the external solver, using the option --download-package 4888 4889 Developer Note: 4890 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4891 4892 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4893 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4894 @*/ 4895 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4896 { 4897 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4898 4899 PetscFunctionBegin; 4900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4901 PetscAssertPointer(flg, 4); 4902 4903 *flg = PETSC_FALSE; 4904 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4905 4906 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4907 MatCheckPreallocated(mat, 1); 4908 4909 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4910 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4911 PetscFunctionReturn(PETSC_SUCCESS); 4912 } 4913 4914 /*@ 4915 MatDuplicate - Duplicates a matrix including the non-zero structure. 4916 4917 Collective 4918 4919 Input Parameters: 4920 + mat - the matrix 4921 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4922 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4923 4924 Output Parameter: 4925 . M - pointer to place new matrix 4926 4927 Level: intermediate 4928 4929 Notes: 4930 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4931 4932 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4933 4934 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. 4935 4936 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4937 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4938 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4939 4940 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4941 @*/ 4942 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4943 { 4944 Mat B; 4945 VecType vtype; 4946 PetscInt i; 4947 PetscObject dm, container_h, container_d; 4948 void (*viewf)(void); 4949 4950 PetscFunctionBegin; 4951 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4952 PetscValidType(mat, 1); 4953 PetscAssertPointer(M, 3); 4954 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4955 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4956 MatCheckPreallocated(mat, 1); 4957 4958 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4959 PetscUseTypeMethod(mat, duplicate, op, M); 4960 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4961 B = *M; 4962 4963 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4964 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4965 PetscCall(MatGetVecType(mat, &vtype)); 4966 PetscCall(MatSetVecType(B, vtype)); 4967 4968 B->stencil.dim = mat->stencil.dim; 4969 B->stencil.noc = mat->stencil.noc; 4970 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4971 B->stencil.dims[i] = mat->stencil.dims[i]; 4972 B->stencil.starts[i] = mat->stencil.starts[i]; 4973 } 4974 4975 B->nooffproczerorows = mat->nooffproczerorows; 4976 B->nooffprocentries = mat->nooffprocentries; 4977 4978 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4979 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4980 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4981 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4982 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4983 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4984 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4985 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4986 PetscFunctionReturn(PETSC_SUCCESS); 4987 } 4988 4989 /*@ 4990 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4991 4992 Logically Collective 4993 4994 Input Parameter: 4995 . mat - the matrix 4996 4997 Output Parameter: 4998 . v - the diagonal of the matrix 4999 5000 Level: intermediate 5001 5002 Note: 5003 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5004 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5005 is larger than `ndiag`, the values of the remaining entries are unspecified. 5006 5007 Currently only correct in parallel for square matrices. 5008 5009 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5010 @*/ 5011 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5012 { 5013 PetscFunctionBegin; 5014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5015 PetscValidType(mat, 1); 5016 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5017 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5018 MatCheckPreallocated(mat, 1); 5019 if (PetscDefined(USE_DEBUG)) { 5020 PetscInt nv, row, col, ndiag; 5021 5022 PetscCall(VecGetLocalSize(v, &nv)); 5023 PetscCall(MatGetLocalSize(mat, &row, &col)); 5024 ndiag = PetscMin(row, col); 5025 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); 5026 } 5027 5028 PetscUseTypeMethod(mat, getdiagonal, v); 5029 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5030 PetscFunctionReturn(PETSC_SUCCESS); 5031 } 5032 5033 /*@ 5034 MatGetRowMin - Gets the minimum value (of the real part) of each 5035 row of the matrix 5036 5037 Logically Collective 5038 5039 Input Parameter: 5040 . mat - the matrix 5041 5042 Output Parameters: 5043 + v - the vector for storing the maximums 5044 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5045 5046 Level: intermediate 5047 5048 Note: 5049 The result of this call are the same as if one converted the matrix to dense format 5050 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5051 5052 This code is only implemented for a couple of matrix formats. 5053 5054 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5055 `MatGetRowMax()` 5056 @*/ 5057 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5058 { 5059 PetscFunctionBegin; 5060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5061 PetscValidType(mat, 1); 5062 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5063 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5064 5065 if (!mat->cmap->N) { 5066 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5067 if (idx) { 5068 PetscInt i, m = mat->rmap->n; 5069 for (i = 0; i < m; i++) idx[i] = -1; 5070 } 5071 } else { 5072 MatCheckPreallocated(mat, 1); 5073 } 5074 PetscUseTypeMethod(mat, getrowmin, v, idx); 5075 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5076 PetscFunctionReturn(PETSC_SUCCESS); 5077 } 5078 5079 /*@ 5080 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5081 row of the matrix 5082 5083 Logically Collective 5084 5085 Input Parameter: 5086 . mat - the matrix 5087 5088 Output Parameters: 5089 + v - the vector for storing the minimums 5090 - idx - the indices of the column found for each row (or `NULL` if not needed) 5091 5092 Level: intermediate 5093 5094 Notes: 5095 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5096 row is 0 (the first column). 5097 5098 This code is only implemented for a couple of matrix formats. 5099 5100 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5101 @*/ 5102 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5103 { 5104 PetscFunctionBegin; 5105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5106 PetscValidType(mat, 1); 5107 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5108 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5109 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5110 5111 if (!mat->cmap->N) { 5112 PetscCall(VecSet(v, 0.0)); 5113 if (idx) { 5114 PetscInt i, m = mat->rmap->n; 5115 for (i = 0; i < m; i++) idx[i] = -1; 5116 } 5117 } else { 5118 MatCheckPreallocated(mat, 1); 5119 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5120 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5121 } 5122 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5123 PetscFunctionReturn(PETSC_SUCCESS); 5124 } 5125 5126 /*@ 5127 MatGetRowMax - Gets the maximum value (of the real part) of each 5128 row of the matrix 5129 5130 Logically Collective 5131 5132 Input Parameter: 5133 . mat - the matrix 5134 5135 Output Parameters: 5136 + v - the vector for storing the maximums 5137 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5138 5139 Level: intermediate 5140 5141 Notes: 5142 The result of this call are the same as if one converted the matrix to dense format 5143 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5144 5145 This code is only implemented for a couple of matrix formats. 5146 5147 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5148 @*/ 5149 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5150 { 5151 PetscFunctionBegin; 5152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5153 PetscValidType(mat, 1); 5154 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5155 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5156 5157 if (!mat->cmap->N) { 5158 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5159 if (idx) { 5160 PetscInt i, m = mat->rmap->n; 5161 for (i = 0; i < m; i++) idx[i] = -1; 5162 } 5163 } else { 5164 MatCheckPreallocated(mat, 1); 5165 PetscUseTypeMethod(mat, getrowmax, v, idx); 5166 } 5167 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5168 PetscFunctionReturn(PETSC_SUCCESS); 5169 } 5170 5171 /*@ 5172 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5173 row of the matrix 5174 5175 Logically Collective 5176 5177 Input Parameter: 5178 . mat - the matrix 5179 5180 Output Parameters: 5181 + v - the vector for storing the maximums 5182 - idx - the indices of the column found for each row (or `NULL` if not needed) 5183 5184 Level: intermediate 5185 5186 Notes: 5187 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5188 row is 0 (the first column). 5189 5190 This code is only implemented for a couple of matrix formats. 5191 5192 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5193 @*/ 5194 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5195 { 5196 PetscFunctionBegin; 5197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5198 PetscValidType(mat, 1); 5199 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5200 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5201 5202 if (!mat->cmap->N) { 5203 PetscCall(VecSet(v, 0.0)); 5204 if (idx) { 5205 PetscInt i, m = mat->rmap->n; 5206 for (i = 0; i < m; i++) idx[i] = -1; 5207 } 5208 } else { 5209 MatCheckPreallocated(mat, 1); 5210 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5211 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5212 } 5213 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5214 PetscFunctionReturn(PETSC_SUCCESS); 5215 } 5216 5217 /*@ 5218 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5219 5220 Logically Collective 5221 5222 Input Parameter: 5223 . mat - the matrix 5224 5225 Output Parameter: 5226 . v - the vector for storing the sum 5227 5228 Level: intermediate 5229 5230 This code is only implemented for a couple of matrix formats. 5231 5232 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5233 @*/ 5234 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5235 { 5236 PetscFunctionBegin; 5237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5238 PetscValidType(mat, 1); 5239 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5241 5242 if (!mat->cmap->N) { 5243 PetscCall(VecSet(v, 0.0)); 5244 } else { 5245 MatCheckPreallocated(mat, 1); 5246 PetscUseTypeMethod(mat, getrowsumabs, v); 5247 } 5248 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5249 PetscFunctionReturn(PETSC_SUCCESS); 5250 } 5251 5252 /*@ 5253 MatGetRowSum - Gets the sum of each row of the matrix 5254 5255 Logically or Neighborhood Collective 5256 5257 Input Parameter: 5258 . mat - the matrix 5259 5260 Output Parameter: 5261 . v - the vector for storing the sum of rows 5262 5263 Level: intermediate 5264 5265 Note: 5266 This code is slow since it is not currently specialized for different formats 5267 5268 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5269 @*/ 5270 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5271 { 5272 Vec ones; 5273 5274 PetscFunctionBegin; 5275 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5276 PetscValidType(mat, 1); 5277 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5278 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5279 MatCheckPreallocated(mat, 1); 5280 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5281 PetscCall(VecSet(ones, 1.)); 5282 PetscCall(MatMult(mat, ones, v)); 5283 PetscCall(VecDestroy(&ones)); 5284 PetscFunctionReturn(PETSC_SUCCESS); 5285 } 5286 5287 /*@ 5288 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5289 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5290 5291 Collective 5292 5293 Input Parameter: 5294 . mat - the matrix to provide the transpose 5295 5296 Output Parameter: 5297 . 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 5298 5299 Level: advanced 5300 5301 Note: 5302 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 5303 routine allows bypassing that call. 5304 5305 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5306 @*/ 5307 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5308 { 5309 MatParentState *rb = NULL; 5310 5311 PetscFunctionBegin; 5312 PetscCall(PetscNew(&rb)); 5313 rb->id = ((PetscObject)mat)->id; 5314 rb->state = 0; 5315 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5316 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5317 PetscFunctionReturn(PETSC_SUCCESS); 5318 } 5319 5320 /*@ 5321 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5322 5323 Collective 5324 5325 Input Parameters: 5326 + mat - the matrix to transpose 5327 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5328 5329 Output Parameter: 5330 . B - the transpose of the matrix 5331 5332 Level: intermediate 5333 5334 Notes: 5335 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5336 5337 `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 5338 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5339 5340 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. 5341 5342 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5343 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5344 5345 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5346 5347 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5348 5349 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5350 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5351 @*/ 5352 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5353 { 5354 PetscContainer rB = NULL; 5355 MatParentState *rb = NULL; 5356 5357 PetscFunctionBegin; 5358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5359 PetscValidType(mat, 1); 5360 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5361 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5362 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5363 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5364 MatCheckPreallocated(mat, 1); 5365 if (reuse == MAT_REUSE_MATRIX) { 5366 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5367 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5368 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5369 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5370 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5371 } 5372 5373 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5374 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5375 PetscUseTypeMethod(mat, transpose, reuse, B); 5376 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5377 } 5378 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5379 5380 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5381 if (reuse != MAT_INPLACE_MATRIX) { 5382 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5383 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5384 rb->state = ((PetscObject)mat)->state; 5385 rb->nonzerostate = mat->nonzerostate; 5386 } 5387 PetscFunctionReturn(PETSC_SUCCESS); 5388 } 5389 5390 /*@ 5391 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5392 5393 Collective 5394 5395 Input Parameter: 5396 . A - the matrix to transpose 5397 5398 Output Parameter: 5399 . 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 5400 numerical portion. 5401 5402 Level: intermediate 5403 5404 Note: 5405 This is not supported for many matrix types, use `MatTranspose()` in those cases 5406 5407 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5408 @*/ 5409 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5410 { 5411 PetscFunctionBegin; 5412 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5413 PetscValidType(A, 1); 5414 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5415 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5416 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5417 PetscUseTypeMethod(A, transposesymbolic, B); 5418 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5419 5420 PetscCall(MatTransposeSetPrecursor(A, *B)); 5421 PetscFunctionReturn(PETSC_SUCCESS); 5422 } 5423 5424 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5425 { 5426 PetscContainer rB; 5427 MatParentState *rb; 5428 5429 PetscFunctionBegin; 5430 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5431 PetscValidType(A, 1); 5432 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5433 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5434 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5435 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5436 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5437 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5438 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5439 PetscFunctionReturn(PETSC_SUCCESS); 5440 } 5441 5442 /*@ 5443 MatIsTranspose - Test whether a matrix is another one's transpose, 5444 or its own, in which case it tests symmetry. 5445 5446 Collective 5447 5448 Input Parameters: 5449 + A - the matrix to test 5450 . B - the matrix to test against, this can equal the first parameter 5451 - tol - tolerance, differences between entries smaller than this are counted as zero 5452 5453 Output Parameter: 5454 . flg - the result 5455 5456 Level: intermediate 5457 5458 Notes: 5459 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5460 test involves parallel copies of the block off-diagonal parts of the matrix. 5461 5462 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5463 @*/ 5464 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5465 { 5466 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5467 5468 PetscFunctionBegin; 5469 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5470 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5471 PetscAssertPointer(flg, 4); 5472 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5473 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5474 *flg = PETSC_FALSE; 5475 if (f && g) { 5476 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5477 PetscCall((*f)(A, B, tol, flg)); 5478 } else { 5479 MatType mattype; 5480 5481 PetscCall(MatGetType(f ? B : A, &mattype)); 5482 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5483 } 5484 PetscFunctionReturn(PETSC_SUCCESS); 5485 } 5486 5487 /*@ 5488 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5489 5490 Collective 5491 5492 Input Parameters: 5493 + mat - the matrix to transpose and complex conjugate 5494 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5495 5496 Output Parameter: 5497 . B - the Hermitian transpose 5498 5499 Level: intermediate 5500 5501 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5502 @*/ 5503 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5504 { 5505 PetscFunctionBegin; 5506 PetscCall(MatTranspose(mat, reuse, B)); 5507 #if defined(PETSC_USE_COMPLEX) 5508 PetscCall(MatConjugate(*B)); 5509 #endif 5510 PetscFunctionReturn(PETSC_SUCCESS); 5511 } 5512 5513 /*@ 5514 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5515 5516 Collective 5517 5518 Input Parameters: 5519 + A - the matrix to test 5520 . B - the matrix to test against, this can equal the first parameter 5521 - tol - tolerance, differences between entries smaller than this are counted as zero 5522 5523 Output Parameter: 5524 . flg - the result 5525 5526 Level: intermediate 5527 5528 Notes: 5529 Only available for `MATAIJ` matrices. 5530 5531 The sequential algorithm 5532 has a running time of the order of the number of nonzeros; the parallel 5533 test involves parallel copies of the block off-diagonal parts of the matrix. 5534 5535 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5536 @*/ 5537 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5538 { 5539 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5540 5541 PetscFunctionBegin; 5542 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5543 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5544 PetscAssertPointer(flg, 4); 5545 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5546 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5547 if (f && g) { 5548 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5549 PetscCall((*f)(A, B, tol, flg)); 5550 } 5551 PetscFunctionReturn(PETSC_SUCCESS); 5552 } 5553 5554 /*@ 5555 MatPermute - Creates a new matrix with rows and columns permuted from the 5556 original. 5557 5558 Collective 5559 5560 Input Parameters: 5561 + mat - the matrix to permute 5562 . row - row permutation, each processor supplies only the permutation for its rows 5563 - col - column permutation, each processor supplies only the permutation for its columns 5564 5565 Output Parameter: 5566 . B - the permuted matrix 5567 5568 Level: advanced 5569 5570 Note: 5571 The index sets map from row/col of permuted matrix to row/col of original matrix. 5572 The index sets should be on the same communicator as mat and have the same local sizes. 5573 5574 Developer Note: 5575 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5576 exploit the fact that row and col are permutations, consider implementing the 5577 more general `MatCreateSubMatrix()` instead. 5578 5579 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5580 @*/ 5581 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5582 { 5583 PetscFunctionBegin; 5584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5585 PetscValidType(mat, 1); 5586 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5587 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5588 PetscAssertPointer(B, 4); 5589 PetscCheckSameComm(mat, 1, row, 2); 5590 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5592 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5593 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5594 MatCheckPreallocated(mat, 1); 5595 5596 if (mat->ops->permute) { 5597 PetscUseTypeMethod(mat, permute, row, col, B); 5598 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5599 } else { 5600 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5601 } 5602 PetscFunctionReturn(PETSC_SUCCESS); 5603 } 5604 5605 /*@ 5606 MatEqual - Compares two matrices. 5607 5608 Collective 5609 5610 Input Parameters: 5611 + A - the first matrix 5612 - B - the second matrix 5613 5614 Output Parameter: 5615 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5616 5617 Level: intermediate 5618 5619 Note: 5620 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 5621 using several randomly created vectors, see `MatMultEqual()`. 5622 5623 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5624 @*/ 5625 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5626 { 5627 PetscFunctionBegin; 5628 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5629 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5630 PetscValidType(A, 1); 5631 PetscValidType(B, 2); 5632 PetscAssertPointer(flg, 3); 5633 PetscCheckSameComm(A, 1, B, 2); 5634 MatCheckPreallocated(A, 1); 5635 MatCheckPreallocated(B, 2); 5636 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5637 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5638 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, 5639 B->cmap->N); 5640 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5641 PetscUseTypeMethod(A, equal, B, flg); 5642 } else { 5643 PetscCall(MatMultEqual(A, B, 10, flg)); 5644 } 5645 PetscFunctionReturn(PETSC_SUCCESS); 5646 } 5647 5648 /*@ 5649 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5650 matrices that are stored as vectors. Either of the two scaling 5651 matrices can be `NULL`. 5652 5653 Collective 5654 5655 Input Parameters: 5656 + mat - the matrix to be scaled 5657 . l - the left scaling vector (or `NULL`) 5658 - r - the right scaling vector (or `NULL`) 5659 5660 Level: intermediate 5661 5662 Note: 5663 `MatDiagonalScale()` computes $A = LAR$, where 5664 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5665 The L scales the rows of the matrix, the R scales the columns of the matrix. 5666 5667 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5668 @*/ 5669 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5670 { 5671 PetscFunctionBegin; 5672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5673 PetscValidType(mat, 1); 5674 if (l) { 5675 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5676 PetscCheckSameComm(mat, 1, l, 2); 5677 } 5678 if (r) { 5679 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5680 PetscCheckSameComm(mat, 1, r, 3); 5681 } 5682 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5683 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5684 MatCheckPreallocated(mat, 1); 5685 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5686 5687 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5688 PetscUseTypeMethod(mat, diagonalscale, l, r); 5689 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5690 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5691 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5692 PetscFunctionReturn(PETSC_SUCCESS); 5693 } 5694 5695 /*@ 5696 MatScale - Scales all elements of a matrix by a given number. 5697 5698 Logically Collective 5699 5700 Input Parameters: 5701 + mat - the matrix to be scaled 5702 - a - the scaling value 5703 5704 Level: intermediate 5705 5706 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5707 @*/ 5708 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5709 { 5710 PetscFunctionBegin; 5711 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5712 PetscValidType(mat, 1); 5713 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5714 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5715 PetscValidLogicalCollectiveScalar(mat, a, 2); 5716 MatCheckPreallocated(mat, 1); 5717 5718 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5719 if (a != (PetscScalar)1.0) { 5720 PetscUseTypeMethod(mat, scale, a); 5721 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5722 } 5723 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5724 PetscFunctionReturn(PETSC_SUCCESS); 5725 } 5726 5727 /*@ 5728 MatNorm - Calculates various norms of a matrix. 5729 5730 Collective 5731 5732 Input Parameters: 5733 + mat - the matrix 5734 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5735 5736 Output Parameter: 5737 . nrm - the resulting norm 5738 5739 Level: intermediate 5740 5741 .seealso: [](ch_matrices), `Mat` 5742 @*/ 5743 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5744 { 5745 PetscFunctionBegin; 5746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5747 PetscValidType(mat, 1); 5748 PetscAssertPointer(nrm, 3); 5749 5750 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5751 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5752 MatCheckPreallocated(mat, 1); 5753 5754 PetscUseTypeMethod(mat, norm, type, nrm); 5755 PetscFunctionReturn(PETSC_SUCCESS); 5756 } 5757 5758 /* 5759 This variable is used to prevent counting of MatAssemblyBegin() that 5760 are called from within a MatAssemblyEnd(). 5761 */ 5762 static PetscInt MatAssemblyEnd_InUse = 0; 5763 /*@ 5764 MatAssemblyBegin - Begins assembling the matrix. This routine should 5765 be called after completing all calls to `MatSetValues()`. 5766 5767 Collective 5768 5769 Input Parameters: 5770 + mat - the matrix 5771 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5772 5773 Level: beginner 5774 5775 Notes: 5776 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5777 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5778 5779 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5780 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5781 using the matrix. 5782 5783 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5784 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 5785 a global collective operation requiring all processes that share the matrix. 5786 5787 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5788 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5789 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5790 5791 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5792 @*/ 5793 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5794 { 5795 PetscFunctionBegin; 5796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5797 PetscValidType(mat, 1); 5798 MatCheckPreallocated(mat, 1); 5799 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5800 if (mat->assembled) { 5801 mat->was_assembled = PETSC_TRUE; 5802 mat->assembled = PETSC_FALSE; 5803 } 5804 5805 if (!MatAssemblyEnd_InUse) { 5806 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5807 PetscTryTypeMethod(mat, assemblybegin, type); 5808 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5809 } else PetscTryTypeMethod(mat, assemblybegin, type); 5810 PetscFunctionReturn(PETSC_SUCCESS); 5811 } 5812 5813 /*@ 5814 MatAssembled - Indicates if a matrix has been assembled and is ready for 5815 use; for example, in matrix-vector product. 5816 5817 Not Collective 5818 5819 Input Parameter: 5820 . mat - the matrix 5821 5822 Output Parameter: 5823 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5824 5825 Level: advanced 5826 5827 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5828 @*/ 5829 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5830 { 5831 PetscFunctionBegin; 5832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5833 PetscAssertPointer(assembled, 2); 5834 *assembled = mat->assembled; 5835 PetscFunctionReturn(PETSC_SUCCESS); 5836 } 5837 5838 /*@ 5839 MatAssemblyEnd - Completes assembling the matrix. This routine should 5840 be called after `MatAssemblyBegin()`. 5841 5842 Collective 5843 5844 Input Parameters: 5845 + mat - the matrix 5846 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5847 5848 Options Database Keys: 5849 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5850 . -mat_view ::ascii_info_detail - Prints more detailed info 5851 . -mat_view - Prints matrix in ASCII format 5852 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5853 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5854 . -display <name> - Sets display name (default is host) 5855 . -draw_pause <sec> - Sets number of seconds to pause after display 5856 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5857 . -viewer_socket_machine <machine> - Machine to use for socket 5858 . -viewer_socket_port <port> - Port number to use for socket 5859 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5860 5861 Level: beginner 5862 5863 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5864 @*/ 5865 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5866 { 5867 static PetscInt inassm = 0; 5868 PetscBool flg = PETSC_FALSE; 5869 5870 PetscFunctionBegin; 5871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5872 PetscValidType(mat, 1); 5873 5874 inassm++; 5875 MatAssemblyEnd_InUse++; 5876 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5877 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5878 PetscTryTypeMethod(mat, assemblyend, type); 5879 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5880 } else PetscTryTypeMethod(mat, assemblyend, type); 5881 5882 /* Flush assembly is not a true assembly */ 5883 if (type != MAT_FLUSH_ASSEMBLY) { 5884 if (mat->num_ass) { 5885 if (!mat->symmetry_eternal) { 5886 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5887 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5888 } 5889 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5890 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5891 } 5892 mat->num_ass++; 5893 mat->assembled = PETSC_TRUE; 5894 mat->ass_nonzerostate = mat->nonzerostate; 5895 } 5896 5897 mat->insertmode = NOT_SET_VALUES; 5898 MatAssemblyEnd_InUse--; 5899 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5900 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5901 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5902 5903 if (mat->checksymmetryonassembly) { 5904 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5905 if (flg) { 5906 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5907 } else { 5908 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5909 } 5910 } 5911 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5912 } 5913 inassm--; 5914 PetscFunctionReturn(PETSC_SUCCESS); 5915 } 5916 5917 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5918 /*@ 5919 MatSetOption - Sets a parameter option for a matrix. Some options 5920 may be specific to certain storage formats. Some options 5921 determine how values will be inserted (or added). Sorted, 5922 row-oriented input will generally assemble the fastest. The default 5923 is row-oriented. 5924 5925 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5926 5927 Input Parameters: 5928 + mat - the matrix 5929 . op - the option, one of those listed below (and possibly others), 5930 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5931 5932 Options Describing Matrix Structure: 5933 + `MAT_SPD` - symmetric positive definite 5934 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5935 . `MAT_HERMITIAN` - transpose is the complex conjugation 5936 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5937 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5938 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5939 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5940 5941 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5942 do not need to be computed (usually at a high cost) 5943 5944 Options For Use with `MatSetValues()`: 5945 Insert a logically dense subblock, which can be 5946 . `MAT_ROW_ORIENTED` - row-oriented (default) 5947 5948 These options reflect the data you pass in with `MatSetValues()`; it has 5949 nothing to do with how the data is stored internally in the matrix 5950 data structure. 5951 5952 When (re)assembling a matrix, we can restrict the input for 5953 efficiency/debugging purposes. These options include 5954 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5955 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5956 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5957 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5958 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5959 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5960 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5961 performance for very large process counts. 5962 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5963 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5964 functions, instead sending only neighbor messages. 5965 5966 Level: intermediate 5967 5968 Notes: 5969 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5970 5971 Some options are relevant only for particular matrix types and 5972 are thus ignored by others. Other options are not supported by 5973 certain matrix types and will generate an error message if set. 5974 5975 If using Fortran to compute a matrix, one may need to 5976 use the column-oriented option (or convert to the row-oriented 5977 format). 5978 5979 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5980 that would generate a new entry in the nonzero structure is instead 5981 ignored. Thus, if memory has not already been allocated for this particular 5982 data, then the insertion is ignored. For dense matrices, in which 5983 the entire array is allocated, no entries are ever ignored. 5984 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5985 5986 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5987 that would generate a new entry in the nonzero structure instead produces 5988 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 5989 5990 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5991 that would generate a new entry that has not been preallocated will 5992 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5993 only.) This is a useful flag when debugging matrix memory preallocation. 5994 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5995 5996 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5997 other processors should be dropped, rather than stashed. 5998 This is useful if you know that the "owning" processor is also 5999 always generating the correct matrix entries, so that PETSc need 6000 not transfer duplicate entries generated on another processor. 6001 6002 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6003 searches during matrix assembly. When this flag is set, the hash table 6004 is created during the first matrix assembly. This hash table is 6005 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6006 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6007 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6008 supported by `MATMPIBAIJ` format only. 6009 6010 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6011 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6012 6013 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6014 a zero location in the matrix 6015 6016 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6017 6018 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6019 zero row routines and thus improves performance for very large process counts. 6020 6021 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6022 part of the matrix (since they should match the upper triangular part). 6023 6024 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6025 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6026 with finite difference schemes with non-periodic boundary conditions. 6027 6028 Developer Note: 6029 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6030 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6031 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6032 not changed. 6033 6034 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6035 @*/ 6036 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6037 { 6038 PetscFunctionBegin; 6039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6040 if (op > 0) { 6041 PetscValidLogicalCollectiveEnum(mat, op, 2); 6042 PetscValidLogicalCollectiveBool(mat, flg, 3); 6043 } 6044 6045 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); 6046 6047 switch (op) { 6048 case MAT_FORCE_DIAGONAL_ENTRIES: 6049 mat->force_diagonals = flg; 6050 PetscFunctionReturn(PETSC_SUCCESS); 6051 case MAT_NO_OFF_PROC_ENTRIES: 6052 mat->nooffprocentries = flg; 6053 PetscFunctionReturn(PETSC_SUCCESS); 6054 case MAT_SUBSET_OFF_PROC_ENTRIES: 6055 mat->assembly_subset = flg; 6056 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6057 #if !defined(PETSC_HAVE_MPIUNI) 6058 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6059 #endif 6060 mat->stash.first_assembly_done = PETSC_FALSE; 6061 } 6062 PetscFunctionReturn(PETSC_SUCCESS); 6063 case MAT_NO_OFF_PROC_ZERO_ROWS: 6064 mat->nooffproczerorows = flg; 6065 PetscFunctionReturn(PETSC_SUCCESS); 6066 case MAT_SPD: 6067 if (flg) { 6068 mat->spd = PETSC_BOOL3_TRUE; 6069 mat->symmetric = PETSC_BOOL3_TRUE; 6070 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6071 } else { 6072 mat->spd = PETSC_BOOL3_FALSE; 6073 } 6074 break; 6075 case MAT_SYMMETRIC: 6076 mat->symmetric = PetscBoolToBool3(flg); 6077 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6078 #if !defined(PETSC_USE_COMPLEX) 6079 mat->hermitian = PetscBoolToBool3(flg); 6080 #endif 6081 break; 6082 case MAT_HERMITIAN: 6083 mat->hermitian = PetscBoolToBool3(flg); 6084 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6085 #if !defined(PETSC_USE_COMPLEX) 6086 mat->symmetric = PetscBoolToBool3(flg); 6087 #endif 6088 break; 6089 case MAT_STRUCTURALLY_SYMMETRIC: 6090 mat->structurally_symmetric = PetscBoolToBool3(flg); 6091 break; 6092 case MAT_SYMMETRY_ETERNAL: 6093 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"); 6094 mat->symmetry_eternal = flg; 6095 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6096 break; 6097 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6098 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"); 6099 mat->structural_symmetry_eternal = flg; 6100 break; 6101 case MAT_SPD_ETERNAL: 6102 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"); 6103 mat->spd_eternal = flg; 6104 if (flg) { 6105 mat->structural_symmetry_eternal = PETSC_TRUE; 6106 mat->symmetry_eternal = PETSC_TRUE; 6107 } 6108 break; 6109 case MAT_STRUCTURE_ONLY: 6110 mat->structure_only = flg; 6111 break; 6112 case MAT_SORTED_FULL: 6113 mat->sortedfull = flg; 6114 break; 6115 default: 6116 break; 6117 } 6118 PetscTryTypeMethod(mat, setoption, op, flg); 6119 PetscFunctionReturn(PETSC_SUCCESS); 6120 } 6121 6122 /*@ 6123 MatGetOption - Gets a parameter option that has been set for a matrix. 6124 6125 Logically Collective 6126 6127 Input Parameters: 6128 + mat - the matrix 6129 - op - the option, this only responds to certain options, check the code for which ones 6130 6131 Output Parameter: 6132 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6133 6134 Level: intermediate 6135 6136 Notes: 6137 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6138 6139 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6140 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6141 6142 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6143 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6144 @*/ 6145 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6146 { 6147 PetscFunctionBegin; 6148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6149 PetscValidType(mat, 1); 6150 6151 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); 6152 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()"); 6153 6154 switch (op) { 6155 case MAT_NO_OFF_PROC_ENTRIES: 6156 *flg = mat->nooffprocentries; 6157 break; 6158 case MAT_NO_OFF_PROC_ZERO_ROWS: 6159 *flg = mat->nooffproczerorows; 6160 break; 6161 case MAT_SYMMETRIC: 6162 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6163 break; 6164 case MAT_HERMITIAN: 6165 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6166 break; 6167 case MAT_STRUCTURALLY_SYMMETRIC: 6168 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6169 break; 6170 case MAT_SPD: 6171 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6172 break; 6173 case MAT_SYMMETRY_ETERNAL: 6174 *flg = mat->symmetry_eternal; 6175 break; 6176 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6177 *flg = mat->symmetry_eternal; 6178 break; 6179 default: 6180 break; 6181 } 6182 PetscFunctionReturn(PETSC_SUCCESS); 6183 } 6184 6185 /*@ 6186 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6187 this routine retains the old nonzero structure. 6188 6189 Logically Collective 6190 6191 Input Parameter: 6192 . mat - the matrix 6193 6194 Level: intermediate 6195 6196 Note: 6197 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. 6198 See the Performance chapter of the users manual for information on preallocating matrices. 6199 6200 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6201 @*/ 6202 PetscErrorCode MatZeroEntries(Mat mat) 6203 { 6204 PetscFunctionBegin; 6205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6206 PetscValidType(mat, 1); 6207 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6208 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"); 6209 MatCheckPreallocated(mat, 1); 6210 6211 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6212 PetscUseTypeMethod(mat, zeroentries); 6213 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6214 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6215 PetscFunctionReturn(PETSC_SUCCESS); 6216 } 6217 6218 /*@ 6219 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6220 of a set of rows and columns of a matrix. 6221 6222 Collective 6223 6224 Input Parameters: 6225 + mat - the matrix 6226 . numRows - the number of rows/columns to zero 6227 . rows - the global row indices 6228 . diag - value put in the diagonal of the eliminated rows 6229 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6230 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6231 6232 Level: intermediate 6233 6234 Notes: 6235 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6236 6237 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6238 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 6239 6240 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6241 Krylov method to take advantage of the known solution on the zeroed rows. 6242 6243 For the parallel case, all processes that share the matrix (i.e., 6244 those in the communicator used for matrix creation) MUST call this 6245 routine, regardless of whether any rows being zeroed are owned by 6246 them. 6247 6248 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6249 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 6250 missing. 6251 6252 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6253 list only rows local to itself). 6254 6255 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6256 6257 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6258 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6259 @*/ 6260 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6261 { 6262 PetscFunctionBegin; 6263 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6264 PetscValidType(mat, 1); 6265 if (numRows) PetscAssertPointer(rows, 3); 6266 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6267 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6268 MatCheckPreallocated(mat, 1); 6269 6270 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6271 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6272 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6273 PetscFunctionReturn(PETSC_SUCCESS); 6274 } 6275 6276 /*@ 6277 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6278 of a set of rows and columns of a matrix. 6279 6280 Collective 6281 6282 Input Parameters: 6283 + mat - the matrix 6284 . is - the rows to zero 6285 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6286 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6287 - b - optional vector of right-hand side, that will be adjusted by provided solution 6288 6289 Level: intermediate 6290 6291 Note: 6292 See `MatZeroRowsColumns()` for details on how this routine operates. 6293 6294 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6295 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6296 @*/ 6297 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6298 { 6299 PetscInt numRows; 6300 const PetscInt *rows; 6301 6302 PetscFunctionBegin; 6303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6304 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6305 PetscValidType(mat, 1); 6306 PetscValidType(is, 2); 6307 PetscCall(ISGetLocalSize(is, &numRows)); 6308 PetscCall(ISGetIndices(is, &rows)); 6309 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6310 PetscCall(ISRestoreIndices(is, &rows)); 6311 PetscFunctionReturn(PETSC_SUCCESS); 6312 } 6313 6314 /*@ 6315 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6316 of a set of rows of a matrix. 6317 6318 Collective 6319 6320 Input Parameters: 6321 + mat - the matrix 6322 . numRows - the number of rows to zero 6323 . rows - the global row indices 6324 . diag - value put in the diagonal of the zeroed rows 6325 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6326 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6327 6328 Level: intermediate 6329 6330 Notes: 6331 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6332 6333 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6334 6335 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6336 Krylov method to take advantage of the known solution on the zeroed rows. 6337 6338 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) 6339 from the matrix. 6340 6341 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6342 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6343 formats this does not alter the nonzero structure. 6344 6345 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6346 of the matrix is not changed the values are 6347 merely zeroed. 6348 6349 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6350 formats can optionally remove the main diagonal entry from the 6351 nonzero structure as well, by passing 0.0 as the final argument). 6352 6353 For the parallel case, all processes that share the matrix (i.e., 6354 those in the communicator used for matrix creation) MUST call this 6355 routine, regardless of whether any rows being zeroed are owned by 6356 them. 6357 6358 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6359 list only rows local to itself). 6360 6361 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6362 owns that are to be zeroed. This saves a global synchronization in the implementation. 6363 6364 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6365 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6366 @*/ 6367 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6368 { 6369 PetscFunctionBegin; 6370 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6371 PetscValidType(mat, 1); 6372 if (numRows) PetscAssertPointer(rows, 3); 6373 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6374 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6375 MatCheckPreallocated(mat, 1); 6376 6377 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6378 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6379 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6380 PetscFunctionReturn(PETSC_SUCCESS); 6381 } 6382 6383 /*@ 6384 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6385 of a set of rows of a matrix indicated by an `IS` 6386 6387 Collective 6388 6389 Input Parameters: 6390 + mat - the matrix 6391 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6392 . diag - value put in all diagonals of eliminated rows 6393 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6394 - b - optional vector of right-hand side, that will be adjusted by provided solution 6395 6396 Level: intermediate 6397 6398 Note: 6399 See `MatZeroRows()` for details on how this routine operates. 6400 6401 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6402 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6403 @*/ 6404 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6405 { 6406 PetscInt numRows = 0; 6407 const PetscInt *rows = NULL; 6408 6409 PetscFunctionBegin; 6410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6411 PetscValidType(mat, 1); 6412 if (is) { 6413 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6414 PetscCall(ISGetLocalSize(is, &numRows)); 6415 PetscCall(ISGetIndices(is, &rows)); 6416 } 6417 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6418 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6419 PetscFunctionReturn(PETSC_SUCCESS); 6420 } 6421 6422 /*@ 6423 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6424 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6425 6426 Collective 6427 6428 Input Parameters: 6429 + mat - the matrix 6430 . numRows - the number of rows to remove 6431 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6432 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6433 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6434 - b - optional vector of right-hand side, that will be adjusted by provided solution 6435 6436 Level: intermediate 6437 6438 Notes: 6439 See `MatZeroRows()` for details on how this routine operates. 6440 6441 The grid coordinates are across the entire grid, not just the local portion 6442 6443 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6444 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6445 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6446 `DM_BOUNDARY_PERIODIC` boundary type. 6447 6448 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 6449 a single value per point) you can skip filling those indices. 6450 6451 Fortran Note: 6452 `idxm` and `idxn` should be declared as 6453 .vb 6454 MatStencil idxm(4, m) 6455 .ve 6456 and the values inserted using 6457 .vb 6458 idxm(MatStencil_i, 1) = i 6459 idxm(MatStencil_j, 1) = j 6460 idxm(MatStencil_k, 1) = k 6461 idxm(MatStencil_c, 1) = c 6462 etc 6463 .ve 6464 6465 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6466 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6467 @*/ 6468 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6469 { 6470 PetscInt dim = mat->stencil.dim; 6471 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6472 PetscInt *dims = mat->stencil.dims + 1; 6473 PetscInt *starts = mat->stencil.starts; 6474 PetscInt *dxm = (PetscInt *)rows; 6475 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6476 6477 PetscFunctionBegin; 6478 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6479 PetscValidType(mat, 1); 6480 if (numRows) PetscAssertPointer(rows, 3); 6481 6482 PetscCall(PetscMalloc1(numRows, &jdxm)); 6483 for (i = 0; i < numRows; ++i) { 6484 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6485 for (j = 0; j < 3 - sdim; ++j) dxm++; 6486 /* Local index in X dir */ 6487 tmp = *dxm++ - starts[0]; 6488 /* Loop over remaining dimensions */ 6489 for (j = 0; j < dim - 1; ++j) { 6490 /* If nonlocal, set index to be negative */ 6491 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6492 /* Update local index */ 6493 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6494 } 6495 /* Skip component slot if necessary */ 6496 if (mat->stencil.noc) dxm++; 6497 /* Local row number */ 6498 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6499 } 6500 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6501 PetscCall(PetscFree(jdxm)); 6502 PetscFunctionReturn(PETSC_SUCCESS); 6503 } 6504 6505 /*@ 6506 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6507 of a set of rows and columns of a matrix. 6508 6509 Collective 6510 6511 Input Parameters: 6512 + mat - the matrix 6513 . numRows - the number of rows/columns to remove 6514 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6515 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6516 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6517 - b - optional vector of right-hand side, that will be adjusted by provided solution 6518 6519 Level: intermediate 6520 6521 Notes: 6522 See `MatZeroRowsColumns()` for details on how this routine operates. 6523 6524 The grid coordinates are across the entire grid, not just the local portion 6525 6526 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6527 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6528 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6529 `DM_BOUNDARY_PERIODIC` boundary type. 6530 6531 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 6532 a single value per point) you can skip filling those indices. 6533 6534 Fortran Note: 6535 `idxm` and `idxn` should be declared as 6536 .vb 6537 MatStencil idxm(4, m) 6538 .ve 6539 and the values inserted using 6540 .vb 6541 idxm(MatStencil_i, 1) = i 6542 idxm(MatStencil_j, 1) = j 6543 idxm(MatStencil_k, 1) = k 6544 idxm(MatStencil_c, 1) = c 6545 etc 6546 .ve 6547 6548 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6549 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6550 @*/ 6551 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6552 { 6553 PetscInt dim = mat->stencil.dim; 6554 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6555 PetscInt *dims = mat->stencil.dims + 1; 6556 PetscInt *starts = mat->stencil.starts; 6557 PetscInt *dxm = (PetscInt *)rows; 6558 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6559 6560 PetscFunctionBegin; 6561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6562 PetscValidType(mat, 1); 6563 if (numRows) PetscAssertPointer(rows, 3); 6564 6565 PetscCall(PetscMalloc1(numRows, &jdxm)); 6566 for (i = 0; i < numRows; ++i) { 6567 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6568 for (j = 0; j < 3 - sdim; ++j) dxm++; 6569 /* Local index in X dir */ 6570 tmp = *dxm++ - starts[0]; 6571 /* Loop over remaining dimensions */ 6572 for (j = 0; j < dim - 1; ++j) { 6573 /* If nonlocal, set index to be negative */ 6574 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6575 /* Update local index */ 6576 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6577 } 6578 /* Skip component slot if necessary */ 6579 if (mat->stencil.noc) dxm++; 6580 /* Local row number */ 6581 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6582 } 6583 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6584 PetscCall(PetscFree(jdxm)); 6585 PetscFunctionReturn(PETSC_SUCCESS); 6586 } 6587 6588 /*@ 6589 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6590 of a set of rows of a matrix; using local numbering of rows. 6591 6592 Collective 6593 6594 Input Parameters: 6595 + mat - the matrix 6596 . numRows - the number of rows to remove 6597 . rows - the local row indices 6598 . diag - value put in all diagonals of eliminated rows 6599 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6600 - b - optional vector of right-hand side, that will be adjusted by provided solution 6601 6602 Level: intermediate 6603 6604 Notes: 6605 Before calling `MatZeroRowsLocal()`, the user must first set the 6606 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6607 6608 See `MatZeroRows()` for details on how this routine operates. 6609 6610 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6611 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6612 @*/ 6613 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6614 { 6615 PetscFunctionBegin; 6616 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6617 PetscValidType(mat, 1); 6618 if (numRows) PetscAssertPointer(rows, 3); 6619 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6620 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6621 MatCheckPreallocated(mat, 1); 6622 6623 if (mat->ops->zerorowslocal) { 6624 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6625 } else { 6626 IS is, newis; 6627 const PetscInt *newRows; 6628 6629 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6630 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6631 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6632 PetscCall(ISGetIndices(newis, &newRows)); 6633 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6634 PetscCall(ISRestoreIndices(newis, &newRows)); 6635 PetscCall(ISDestroy(&newis)); 6636 PetscCall(ISDestroy(&is)); 6637 } 6638 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6639 PetscFunctionReturn(PETSC_SUCCESS); 6640 } 6641 6642 /*@ 6643 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6644 of a set of rows of a matrix; using local numbering of rows. 6645 6646 Collective 6647 6648 Input Parameters: 6649 + mat - the matrix 6650 . is - index set of rows to remove 6651 . diag - value put in all diagonals of eliminated rows 6652 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6653 - b - optional vector of right-hand side, that will be adjusted by provided solution 6654 6655 Level: intermediate 6656 6657 Notes: 6658 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6659 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6660 6661 See `MatZeroRows()` for details on how this routine operates. 6662 6663 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6664 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6665 @*/ 6666 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6667 { 6668 PetscInt numRows; 6669 const PetscInt *rows; 6670 6671 PetscFunctionBegin; 6672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6673 PetscValidType(mat, 1); 6674 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6675 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6676 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6677 MatCheckPreallocated(mat, 1); 6678 6679 PetscCall(ISGetLocalSize(is, &numRows)); 6680 PetscCall(ISGetIndices(is, &rows)); 6681 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6682 PetscCall(ISRestoreIndices(is, &rows)); 6683 PetscFunctionReturn(PETSC_SUCCESS); 6684 } 6685 6686 /*@ 6687 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6688 of a set of rows and columns of a matrix; using local numbering of rows. 6689 6690 Collective 6691 6692 Input Parameters: 6693 + mat - the matrix 6694 . numRows - the number of rows to remove 6695 . rows - the global row indices 6696 . diag - value put in all diagonals of eliminated rows 6697 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6698 - b - optional vector of right-hand side, that will be adjusted by provided solution 6699 6700 Level: intermediate 6701 6702 Notes: 6703 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6704 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6705 6706 See `MatZeroRowsColumns()` for details on how this routine operates. 6707 6708 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6709 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6710 @*/ 6711 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6712 { 6713 IS is, newis; 6714 const PetscInt *newRows; 6715 6716 PetscFunctionBegin; 6717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6718 PetscValidType(mat, 1); 6719 if (numRows) PetscAssertPointer(rows, 3); 6720 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6721 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6722 MatCheckPreallocated(mat, 1); 6723 6724 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6725 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6726 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6727 PetscCall(ISGetIndices(newis, &newRows)); 6728 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6729 PetscCall(ISRestoreIndices(newis, &newRows)); 6730 PetscCall(ISDestroy(&newis)); 6731 PetscCall(ISDestroy(&is)); 6732 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6733 PetscFunctionReturn(PETSC_SUCCESS); 6734 } 6735 6736 /*@ 6737 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6738 of a set of rows and columns of a matrix; using local numbering of rows. 6739 6740 Collective 6741 6742 Input Parameters: 6743 + mat - the matrix 6744 . is - index set of rows to remove 6745 . diag - value put in all diagonals of eliminated rows 6746 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6747 - b - optional vector of right-hand side, that will be adjusted by provided solution 6748 6749 Level: intermediate 6750 6751 Notes: 6752 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6753 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6754 6755 See `MatZeroRowsColumns()` for details on how this routine operates. 6756 6757 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6758 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6759 @*/ 6760 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6761 { 6762 PetscInt numRows; 6763 const PetscInt *rows; 6764 6765 PetscFunctionBegin; 6766 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6767 PetscValidType(mat, 1); 6768 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6769 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6770 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6771 MatCheckPreallocated(mat, 1); 6772 6773 PetscCall(ISGetLocalSize(is, &numRows)); 6774 PetscCall(ISGetIndices(is, &rows)); 6775 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6776 PetscCall(ISRestoreIndices(is, &rows)); 6777 PetscFunctionReturn(PETSC_SUCCESS); 6778 } 6779 6780 /*@ 6781 MatGetSize - Returns the numbers of rows and columns in a matrix. 6782 6783 Not Collective 6784 6785 Input Parameter: 6786 . mat - the matrix 6787 6788 Output Parameters: 6789 + m - the number of global rows 6790 - n - the number of global columns 6791 6792 Level: beginner 6793 6794 Note: 6795 Both output parameters can be `NULL` on input. 6796 6797 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6798 @*/ 6799 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6800 { 6801 PetscFunctionBegin; 6802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6803 if (m) *m = mat->rmap->N; 6804 if (n) *n = mat->cmap->N; 6805 PetscFunctionReturn(PETSC_SUCCESS); 6806 } 6807 6808 /*@ 6809 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6810 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6811 6812 Not Collective 6813 6814 Input Parameter: 6815 . mat - the matrix 6816 6817 Output Parameters: 6818 + m - the number of local rows, use `NULL` to not obtain this value 6819 - n - the number of local columns, use `NULL` to not obtain this value 6820 6821 Level: beginner 6822 6823 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6824 @*/ 6825 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6826 { 6827 PetscFunctionBegin; 6828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6829 if (m) PetscAssertPointer(m, 2); 6830 if (n) PetscAssertPointer(n, 3); 6831 if (m) *m = mat->rmap->n; 6832 if (n) *n = mat->cmap->n; 6833 PetscFunctionReturn(PETSC_SUCCESS); 6834 } 6835 6836 /*@ 6837 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6838 vector one multiplies this matrix by that are owned by this processor. 6839 6840 Not Collective, unless matrix has not been allocated, then collective 6841 6842 Input Parameter: 6843 . mat - the matrix 6844 6845 Output Parameters: 6846 + m - the global index of the first local column, use `NULL` to not obtain this value 6847 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6848 6849 Level: developer 6850 6851 Notes: 6852 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6853 6854 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6855 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6856 6857 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6858 the local values in the matrix. 6859 6860 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6861 Layouts](sec_matlayout) for details on matrix layouts. 6862 6863 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6864 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6865 @*/ 6866 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6867 { 6868 PetscFunctionBegin; 6869 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6870 PetscValidType(mat, 1); 6871 if (m) PetscAssertPointer(m, 2); 6872 if (n) PetscAssertPointer(n, 3); 6873 MatCheckPreallocated(mat, 1); 6874 if (m) *m = mat->cmap->rstart; 6875 if (n) *n = mat->cmap->rend; 6876 PetscFunctionReturn(PETSC_SUCCESS); 6877 } 6878 6879 /*@ 6880 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6881 this MPI process. 6882 6883 Not Collective 6884 6885 Input Parameter: 6886 . mat - the matrix 6887 6888 Output Parameters: 6889 + m - the global index of the first local row, use `NULL` to not obtain this value 6890 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6891 6892 Level: beginner 6893 6894 Notes: 6895 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6896 6897 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6898 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6899 6900 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6901 the local values in the matrix. 6902 6903 The high argument is one more than the last element stored locally. 6904 6905 For all matrices it returns the range of matrix rows associated with rows of a vector that 6906 would contain the result of a matrix vector product with this matrix. See [Matrix 6907 Layouts](sec_matlayout) for details on matrix layouts. 6908 6909 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6910 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6911 @*/ 6912 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6913 { 6914 PetscFunctionBegin; 6915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6916 PetscValidType(mat, 1); 6917 if (m) PetscAssertPointer(m, 2); 6918 if (n) PetscAssertPointer(n, 3); 6919 MatCheckPreallocated(mat, 1); 6920 if (m) *m = mat->rmap->rstart; 6921 if (n) *n = mat->rmap->rend; 6922 PetscFunctionReturn(PETSC_SUCCESS); 6923 } 6924 6925 /*@C 6926 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6927 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6928 6929 Not Collective, unless matrix has not been allocated 6930 6931 Input Parameter: 6932 . mat - the matrix 6933 6934 Output Parameter: 6935 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6936 where `size` is the number of MPI processes used by `mat` 6937 6938 Level: beginner 6939 6940 Notes: 6941 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6942 6943 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6944 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6945 6946 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6947 the local values in the matrix. 6948 6949 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6950 would contain the result of a matrix vector product with this matrix. See [Matrix 6951 Layouts](sec_matlayout) for details on matrix layouts. 6952 6953 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6954 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6955 `DMDAGetGhostCorners()`, `DM` 6956 @*/ 6957 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6958 { 6959 PetscFunctionBegin; 6960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6961 PetscValidType(mat, 1); 6962 MatCheckPreallocated(mat, 1); 6963 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6964 PetscFunctionReturn(PETSC_SUCCESS); 6965 } 6966 6967 /*@C 6968 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6969 vector one multiplies this vector by that are owned by each processor. 6970 6971 Not Collective, unless matrix has not been allocated 6972 6973 Input Parameter: 6974 . mat - the matrix 6975 6976 Output Parameter: 6977 . ranges - start of each processors portion plus one more than the total length at the end 6978 6979 Level: beginner 6980 6981 Notes: 6982 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6983 6984 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6985 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6986 6987 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6988 the local values in the matrix. 6989 6990 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6991 Layouts](sec_matlayout) for details on matrix layouts. 6992 6993 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6994 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6995 `DMDAGetGhostCorners()`, `DM` 6996 @*/ 6997 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6998 { 6999 PetscFunctionBegin; 7000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7001 PetscValidType(mat, 1); 7002 MatCheckPreallocated(mat, 1); 7003 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7004 PetscFunctionReturn(PETSC_SUCCESS); 7005 } 7006 7007 /*@ 7008 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7009 7010 Not Collective 7011 7012 Input Parameter: 7013 . A - matrix 7014 7015 Output Parameters: 7016 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7017 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7018 7019 Level: intermediate 7020 7021 Note: 7022 You should call `ISDestroy()` on the returned `IS` 7023 7024 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7025 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7026 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7027 details on matrix layouts. 7028 7029 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7030 @*/ 7031 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7032 { 7033 PetscErrorCode (*f)(Mat, IS *, IS *); 7034 7035 PetscFunctionBegin; 7036 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7037 PetscValidType(A, 1); 7038 MatCheckPreallocated(A, 1); 7039 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7040 if (f) { 7041 PetscCall((*f)(A, rows, cols)); 7042 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7043 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7044 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7045 } 7046 PetscFunctionReturn(PETSC_SUCCESS); 7047 } 7048 7049 /*@ 7050 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7051 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7052 to complete the factorization. 7053 7054 Collective 7055 7056 Input Parameters: 7057 + fact - the factorized matrix obtained with `MatGetFactor()` 7058 . mat - the matrix 7059 . row - row permutation 7060 . col - column permutation 7061 - info - structure containing 7062 .vb 7063 levels - number of levels of fill. 7064 expected fill - as ratio of original fill. 7065 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7066 missing diagonal entries) 7067 .ve 7068 7069 Level: developer 7070 7071 Notes: 7072 See [Matrix Factorization](sec_matfactor) for additional information. 7073 7074 Most users should employ the `KSP` interface for linear solvers 7075 instead of working directly with matrix algebra routines such as this. 7076 See, e.g., `KSPCreate()`. 7077 7078 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7079 7080 Fortran Note: 7081 A valid (non-null) `info` argument must be provided 7082 7083 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7084 `MatGetOrdering()`, `MatFactorInfo` 7085 @*/ 7086 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7087 { 7088 PetscFunctionBegin; 7089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7090 PetscValidType(mat, 2); 7091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7092 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7093 PetscAssertPointer(info, 5); 7094 PetscAssertPointer(fact, 1); 7095 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7096 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7097 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7098 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7099 MatCheckPreallocated(mat, 2); 7100 7101 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7102 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7103 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7104 PetscFunctionReturn(PETSC_SUCCESS); 7105 } 7106 7107 /*@ 7108 MatICCFactorSymbolic - Performs symbolic incomplete 7109 Cholesky factorization for a symmetric matrix. Use 7110 `MatCholeskyFactorNumeric()` to complete the factorization. 7111 7112 Collective 7113 7114 Input Parameters: 7115 + fact - the factorized matrix obtained with `MatGetFactor()` 7116 . mat - the matrix to be factored 7117 . perm - row and column permutation 7118 - info - structure containing 7119 .vb 7120 levels - number of levels of fill. 7121 expected fill - as ratio of original fill. 7122 .ve 7123 7124 Level: developer 7125 7126 Notes: 7127 Most users should employ the `KSP` interface for linear solvers 7128 instead of working directly with matrix algebra routines such as this. 7129 See, e.g., `KSPCreate()`. 7130 7131 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7132 7133 Fortran Note: 7134 A valid (non-null) `info` argument must be provided 7135 7136 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7137 @*/ 7138 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7139 { 7140 PetscFunctionBegin; 7141 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7142 PetscValidType(mat, 2); 7143 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7144 PetscAssertPointer(info, 4); 7145 PetscAssertPointer(fact, 1); 7146 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7147 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7148 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7149 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7150 MatCheckPreallocated(mat, 2); 7151 7152 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7153 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7154 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7155 PetscFunctionReturn(PETSC_SUCCESS); 7156 } 7157 7158 /*@C 7159 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7160 points to an array of valid matrices, they may be reused to store the new 7161 submatrices. 7162 7163 Collective 7164 7165 Input Parameters: 7166 + mat - the matrix 7167 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7168 . irow - index set of rows to extract 7169 . icol - index set of columns to extract 7170 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7171 7172 Output Parameter: 7173 . submat - the array of submatrices 7174 7175 Level: advanced 7176 7177 Notes: 7178 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7179 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7180 to extract a parallel submatrix. 7181 7182 Some matrix types place restrictions on the row and column 7183 indices, such as that they be sorted or that they be equal to each other. 7184 7185 The index sets may not have duplicate entries. 7186 7187 When extracting submatrices from a parallel matrix, each processor can 7188 form a different submatrix by setting the rows and columns of its 7189 individual index sets according to the local submatrix desired. 7190 7191 When finished using the submatrices, the user should destroy 7192 them with `MatDestroySubMatrices()`. 7193 7194 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7195 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7196 7197 This routine creates the matrices in submat; you should NOT create them before 7198 calling it. It also allocates the array of matrix pointers submat. 7199 7200 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7201 request one row/column in a block, they must request all rows/columns that are in 7202 that block. For example, if the block size is 2 you cannot request just row 0 and 7203 column 0. 7204 7205 Fortran Note: 7206 .vb 7207 Mat, pointer :: submat(:) 7208 .ve 7209 7210 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7211 @*/ 7212 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7213 { 7214 PetscInt i; 7215 PetscBool eq; 7216 7217 PetscFunctionBegin; 7218 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7219 PetscValidType(mat, 1); 7220 if (n) { 7221 PetscAssertPointer(irow, 3); 7222 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7223 PetscAssertPointer(icol, 4); 7224 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7225 } 7226 PetscAssertPointer(submat, 6); 7227 if (n && scall == MAT_REUSE_MATRIX) { 7228 PetscAssertPointer(*submat, 6); 7229 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7230 } 7231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7232 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7233 MatCheckPreallocated(mat, 1); 7234 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7235 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7236 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7237 for (i = 0; i < n; i++) { 7238 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7239 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7240 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7241 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7242 if (mat->boundtocpu && mat->bindingpropagates) { 7243 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7244 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7245 } 7246 #endif 7247 } 7248 PetscFunctionReturn(PETSC_SUCCESS); 7249 } 7250 7251 /*@C 7252 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7253 7254 Collective 7255 7256 Input Parameters: 7257 + mat - the matrix 7258 . n - the number of submatrixes to be extracted 7259 . irow - index set of rows to extract 7260 . icol - index set of columns to extract 7261 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7262 7263 Output Parameter: 7264 . submat - the array of submatrices 7265 7266 Level: advanced 7267 7268 Note: 7269 This is used by `PCGASM` 7270 7271 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7272 @*/ 7273 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7274 { 7275 PetscInt i; 7276 PetscBool eq; 7277 7278 PetscFunctionBegin; 7279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7280 PetscValidType(mat, 1); 7281 if (n) { 7282 PetscAssertPointer(irow, 3); 7283 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7284 PetscAssertPointer(icol, 4); 7285 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7286 } 7287 PetscAssertPointer(submat, 6); 7288 if (n && scall == MAT_REUSE_MATRIX) { 7289 PetscAssertPointer(*submat, 6); 7290 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7291 } 7292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7294 MatCheckPreallocated(mat, 1); 7295 7296 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7297 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7298 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7299 for (i = 0; i < n; i++) { 7300 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7301 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7302 } 7303 PetscFunctionReturn(PETSC_SUCCESS); 7304 } 7305 7306 /*@C 7307 MatDestroyMatrices - Destroys an array of matrices 7308 7309 Collective 7310 7311 Input Parameters: 7312 + n - the number of local matrices 7313 - mat - the matrices (this is a pointer to the array of matrices) 7314 7315 Level: advanced 7316 7317 Notes: 7318 Frees not only the matrices, but also the array that contains the matrices 7319 7320 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7321 7322 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7323 @*/ 7324 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7325 { 7326 PetscInt i; 7327 7328 PetscFunctionBegin; 7329 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7330 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7331 PetscAssertPointer(mat, 2); 7332 7333 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7334 7335 /* memory is allocated even if n = 0 */ 7336 PetscCall(PetscFree(*mat)); 7337 PetscFunctionReturn(PETSC_SUCCESS); 7338 } 7339 7340 /*@C 7341 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7342 7343 Collective 7344 7345 Input Parameters: 7346 + n - the number of local matrices 7347 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7348 7349 Level: advanced 7350 7351 Note: 7352 Frees not only the matrices, but also the array that contains the matrices 7353 7354 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7355 @*/ 7356 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7357 { 7358 Mat mat0; 7359 7360 PetscFunctionBegin; 7361 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7362 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7363 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7364 PetscAssertPointer(mat, 2); 7365 7366 mat0 = (*mat)[0]; 7367 if (mat0 && mat0->ops->destroysubmatrices) { 7368 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7369 } else { 7370 PetscCall(MatDestroyMatrices(n, mat)); 7371 } 7372 PetscFunctionReturn(PETSC_SUCCESS); 7373 } 7374 7375 /*@ 7376 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7377 7378 Collective 7379 7380 Input Parameter: 7381 . mat - the matrix 7382 7383 Output Parameter: 7384 . matstruct - the sequential matrix with the nonzero structure of `mat` 7385 7386 Level: developer 7387 7388 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7389 @*/ 7390 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7391 { 7392 PetscFunctionBegin; 7393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7394 PetscAssertPointer(matstruct, 2); 7395 7396 PetscValidType(mat, 1); 7397 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7398 MatCheckPreallocated(mat, 1); 7399 7400 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7401 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7402 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7403 PetscFunctionReturn(PETSC_SUCCESS); 7404 } 7405 7406 /*@C 7407 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7408 7409 Collective 7410 7411 Input Parameter: 7412 . mat - the matrix 7413 7414 Level: advanced 7415 7416 Note: 7417 This is not needed, one can just call `MatDestroy()` 7418 7419 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7420 @*/ 7421 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7422 { 7423 PetscFunctionBegin; 7424 PetscAssertPointer(mat, 1); 7425 PetscCall(MatDestroy(mat)); 7426 PetscFunctionReturn(PETSC_SUCCESS); 7427 } 7428 7429 /*@ 7430 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7431 replaces the index sets by larger ones that represent submatrices with 7432 additional overlap. 7433 7434 Collective 7435 7436 Input Parameters: 7437 + mat - the matrix 7438 . n - the number of index sets 7439 . is - the array of index sets (these index sets will changed during the call) 7440 - ov - the additional overlap requested 7441 7442 Options Database Key: 7443 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7444 7445 Level: developer 7446 7447 Note: 7448 The computed overlap preserves the matrix block sizes when the blocks are square. 7449 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7450 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7451 7452 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7453 @*/ 7454 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7455 { 7456 PetscInt i, bs, cbs; 7457 7458 PetscFunctionBegin; 7459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7460 PetscValidType(mat, 1); 7461 PetscValidLogicalCollectiveInt(mat, n, 2); 7462 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7463 if (n) { 7464 PetscAssertPointer(is, 3); 7465 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7466 } 7467 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7468 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7469 MatCheckPreallocated(mat, 1); 7470 7471 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7472 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7473 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7474 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7475 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7476 if (bs == cbs) { 7477 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7478 } 7479 PetscFunctionReturn(PETSC_SUCCESS); 7480 } 7481 7482 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7483 7484 /*@ 7485 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7486 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7487 additional overlap. 7488 7489 Collective 7490 7491 Input Parameters: 7492 + mat - the matrix 7493 . n - the number of index sets 7494 . is - the array of index sets (these index sets will changed during the call) 7495 - ov - the additional overlap requested 7496 7497 ` Options Database Key: 7498 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7499 7500 Level: developer 7501 7502 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7503 @*/ 7504 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7505 { 7506 PetscInt i; 7507 7508 PetscFunctionBegin; 7509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7510 PetscValidType(mat, 1); 7511 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7512 if (n) { 7513 PetscAssertPointer(is, 3); 7514 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7515 } 7516 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7517 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7518 MatCheckPreallocated(mat, 1); 7519 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7520 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7521 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7522 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7523 PetscFunctionReturn(PETSC_SUCCESS); 7524 } 7525 7526 /*@ 7527 MatGetBlockSize - Returns the matrix block size. 7528 7529 Not Collective 7530 7531 Input Parameter: 7532 . mat - the matrix 7533 7534 Output Parameter: 7535 . bs - block size 7536 7537 Level: intermediate 7538 7539 Notes: 7540 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7541 7542 If the block size has not been set yet this routine returns 1. 7543 7544 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7545 @*/ 7546 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7547 { 7548 PetscFunctionBegin; 7549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7550 PetscAssertPointer(bs, 2); 7551 *bs = mat->rmap->bs; 7552 PetscFunctionReturn(PETSC_SUCCESS); 7553 } 7554 7555 /*@ 7556 MatGetBlockSizes - Returns the matrix block row and column sizes. 7557 7558 Not Collective 7559 7560 Input Parameter: 7561 . mat - the matrix 7562 7563 Output Parameters: 7564 + rbs - row block size 7565 - cbs - column 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 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7572 7573 If a block size has not been set yet this routine returns 1. 7574 7575 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7576 @*/ 7577 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7578 { 7579 PetscFunctionBegin; 7580 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7581 if (rbs) PetscAssertPointer(rbs, 2); 7582 if (cbs) PetscAssertPointer(cbs, 3); 7583 if (rbs) *rbs = mat->rmap->bs; 7584 if (cbs) *cbs = mat->cmap->bs; 7585 PetscFunctionReturn(PETSC_SUCCESS); 7586 } 7587 7588 /*@ 7589 MatSetBlockSize - Sets the matrix block size. 7590 7591 Logically Collective 7592 7593 Input Parameters: 7594 + mat - the matrix 7595 - bs - block size 7596 7597 Level: intermediate 7598 7599 Notes: 7600 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7601 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7602 7603 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7604 is compatible with the matrix local sizes. 7605 7606 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7607 @*/ 7608 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7609 { 7610 PetscFunctionBegin; 7611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7612 PetscValidLogicalCollectiveInt(mat, bs, 2); 7613 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7614 PetscFunctionReturn(PETSC_SUCCESS); 7615 } 7616 7617 typedef struct { 7618 PetscInt n; 7619 IS *is; 7620 Mat *mat; 7621 PetscObjectState nonzerostate; 7622 Mat C; 7623 } EnvelopeData; 7624 7625 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7626 { 7627 EnvelopeData *edata = (EnvelopeData *)*ptr; 7628 7629 PetscFunctionBegin; 7630 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7631 PetscCall(PetscFree(edata->is)); 7632 PetscCall(PetscFree(edata)); 7633 PetscFunctionReturn(PETSC_SUCCESS); 7634 } 7635 7636 /*@ 7637 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7638 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7639 7640 Collective 7641 7642 Input Parameter: 7643 . mat - the matrix 7644 7645 Level: intermediate 7646 7647 Notes: 7648 There can be zeros within the blocks 7649 7650 The blocks can overlap between processes, including laying on more than two processes 7651 7652 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7653 @*/ 7654 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7655 { 7656 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7657 PetscInt *diag, *odiag, sc; 7658 VecScatter scatter; 7659 PetscScalar *seqv; 7660 const PetscScalar *parv; 7661 const PetscInt *ia, *ja; 7662 PetscBool set, flag, done; 7663 Mat AA = mat, A; 7664 MPI_Comm comm; 7665 PetscMPIInt rank, size, tag; 7666 MPI_Status status; 7667 PetscContainer container; 7668 EnvelopeData *edata; 7669 Vec seq, par; 7670 IS isglobal; 7671 7672 PetscFunctionBegin; 7673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7674 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7675 if (!set || !flag) { 7676 /* TODO: only needs nonzero structure of transpose */ 7677 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7678 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7679 } 7680 PetscCall(MatAIJGetLocalMat(AA, &A)); 7681 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7682 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7683 7684 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7685 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7686 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7687 PetscCallMPI(MPI_Comm_size(comm, &size)); 7688 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7689 7690 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7691 7692 if (rank > 0) { 7693 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7694 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7695 } 7696 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7697 for (i = 0; i < n; i++) { 7698 env = PetscMax(env, ja[ia[i + 1] - 1]); 7699 II = rstart + i; 7700 if (env == II) { 7701 starts[lblocks] = tbs; 7702 sizes[lblocks++] = 1 + II - tbs; 7703 tbs = 1 + II; 7704 } 7705 } 7706 if (rank < size - 1) { 7707 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7708 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7709 } 7710 7711 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7712 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7713 PetscCall(MatDestroy(&A)); 7714 7715 PetscCall(PetscNew(&edata)); 7716 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7717 edata->n = lblocks; 7718 /* create IS needed for extracting blocks from the original matrix */ 7719 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7720 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7721 7722 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7723 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7724 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7725 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7726 PetscCall(MatSetType(edata->C, MATAIJ)); 7727 7728 /* Communicate the start and end of each row, from each block to the correct rank */ 7729 /* TODO: Use PetscSF instead of VecScatter */ 7730 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7731 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7732 PetscCall(VecGetArrayWrite(seq, &seqv)); 7733 for (PetscInt i = 0; i < lblocks; i++) { 7734 for (PetscInt j = 0; j < sizes[i]; j++) { 7735 seqv[cnt] = starts[i]; 7736 seqv[cnt + 1] = starts[i] + sizes[i]; 7737 cnt += 2; 7738 } 7739 } 7740 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7741 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7742 sc -= cnt; 7743 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7744 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7745 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7746 PetscCall(ISDestroy(&isglobal)); 7747 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7748 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7749 PetscCall(VecScatterDestroy(&scatter)); 7750 PetscCall(VecDestroy(&seq)); 7751 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7752 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7753 PetscCall(VecGetArrayRead(par, &parv)); 7754 cnt = 0; 7755 PetscCall(MatGetSize(mat, NULL, &n)); 7756 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7757 PetscInt start, end, d = 0, od = 0; 7758 7759 start = (PetscInt)PetscRealPart(parv[cnt]); 7760 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7761 cnt += 2; 7762 7763 if (start < cstart) { 7764 od += cstart - start + n - cend; 7765 d += cend - cstart; 7766 } else if (start < cend) { 7767 od += n - cend; 7768 d += cend - start; 7769 } else od += n - start; 7770 if (end <= cstart) { 7771 od -= cstart - end + n - cend; 7772 d -= cend - cstart; 7773 } else if (end < cend) { 7774 od -= n - cend; 7775 d -= cend - end; 7776 } else od -= n - end; 7777 7778 odiag[i] = od; 7779 diag[i] = d; 7780 } 7781 PetscCall(VecRestoreArrayRead(par, &parv)); 7782 PetscCall(VecDestroy(&par)); 7783 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7784 PetscCall(PetscFree2(diag, odiag)); 7785 PetscCall(PetscFree2(sizes, starts)); 7786 7787 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7788 PetscCall(PetscContainerSetPointer(container, edata)); 7789 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7790 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7791 PetscCall(PetscObjectDereference((PetscObject)container)); 7792 PetscFunctionReturn(PETSC_SUCCESS); 7793 } 7794 7795 /*@ 7796 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7797 7798 Collective 7799 7800 Input Parameters: 7801 + A - the matrix 7802 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7803 7804 Output Parameter: 7805 . C - matrix with inverted block diagonal of `A` 7806 7807 Level: advanced 7808 7809 Note: 7810 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7811 7812 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7813 @*/ 7814 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7815 { 7816 PetscContainer container; 7817 EnvelopeData *edata; 7818 PetscObjectState nonzerostate; 7819 7820 PetscFunctionBegin; 7821 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7822 if (!container) { 7823 PetscCall(MatComputeVariableBlockEnvelope(A)); 7824 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7825 } 7826 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7827 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7828 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7829 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7830 7831 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7832 *C = edata->C; 7833 7834 for (PetscInt i = 0; i < edata->n; i++) { 7835 Mat D; 7836 PetscScalar *dvalues; 7837 7838 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7839 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7840 PetscCall(MatSeqDenseInvert(D)); 7841 PetscCall(MatDenseGetArray(D, &dvalues)); 7842 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7843 PetscCall(MatDestroy(&D)); 7844 } 7845 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7846 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7847 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7848 PetscFunctionReturn(PETSC_SUCCESS); 7849 } 7850 7851 /*@ 7852 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7853 7854 Not Collective 7855 7856 Input Parameters: 7857 + mat - the matrix 7858 . nblocks - the number of blocks on this process, each block can only exist on a single process 7859 - bsizes - the block sizes 7860 7861 Level: intermediate 7862 7863 Notes: 7864 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7865 7866 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. 7867 7868 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7869 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7870 @*/ 7871 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7872 { 7873 PetscInt ncnt = 0, nlocal; 7874 7875 PetscFunctionBegin; 7876 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7877 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7878 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); 7879 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7880 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); 7881 PetscCall(PetscFree(mat->bsizes)); 7882 mat->nblocks = nblocks; 7883 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7884 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7885 PetscFunctionReturn(PETSC_SUCCESS); 7886 } 7887 7888 /*@C 7889 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7890 7891 Not Collective; No Fortran Support 7892 7893 Input Parameter: 7894 . mat - the matrix 7895 7896 Output Parameters: 7897 + nblocks - the number of blocks on this process 7898 - bsizes - the block sizes 7899 7900 Level: intermediate 7901 7902 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7903 @*/ 7904 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7905 { 7906 PetscFunctionBegin; 7907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7908 if (nblocks) *nblocks = mat->nblocks; 7909 if (bsizes) *bsizes = mat->bsizes; 7910 PetscFunctionReturn(PETSC_SUCCESS); 7911 } 7912 7913 /*@ 7914 MatSetBlockSizes - Sets the matrix block row and column sizes. 7915 7916 Logically Collective 7917 7918 Input Parameters: 7919 + mat - the matrix 7920 . rbs - row block size 7921 - cbs - column block size 7922 7923 Level: intermediate 7924 7925 Notes: 7926 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7927 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7928 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7929 7930 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7931 are compatible with the matrix local sizes. 7932 7933 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7934 7935 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7936 @*/ 7937 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7938 { 7939 PetscFunctionBegin; 7940 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7941 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7942 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7943 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7944 if (mat->rmap->refcnt) { 7945 ISLocalToGlobalMapping l2g = NULL; 7946 PetscLayout nmap = NULL; 7947 7948 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7949 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7950 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7951 mat->rmap = nmap; 7952 mat->rmap->mapping = l2g; 7953 } 7954 if (mat->cmap->refcnt) { 7955 ISLocalToGlobalMapping l2g = NULL; 7956 PetscLayout nmap = NULL; 7957 7958 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7959 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7960 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7961 mat->cmap = nmap; 7962 mat->cmap->mapping = l2g; 7963 } 7964 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7965 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7966 PetscFunctionReturn(PETSC_SUCCESS); 7967 } 7968 7969 /*@ 7970 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7971 7972 Logically Collective 7973 7974 Input Parameters: 7975 + mat - the matrix 7976 . fromRow - matrix from which to copy row block size 7977 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7978 7979 Level: developer 7980 7981 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7982 @*/ 7983 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7984 { 7985 PetscFunctionBegin; 7986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7987 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7988 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7989 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7990 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7991 PetscFunctionReturn(PETSC_SUCCESS); 7992 } 7993 7994 /*@ 7995 MatResidual - Default routine to calculate the residual r = b - Ax 7996 7997 Collective 7998 7999 Input Parameters: 8000 + mat - the matrix 8001 . b - the right-hand-side 8002 - x - the approximate solution 8003 8004 Output Parameter: 8005 . r - location to store the residual 8006 8007 Level: developer 8008 8009 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8010 @*/ 8011 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8012 { 8013 PetscFunctionBegin; 8014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8015 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8016 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8017 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8018 PetscValidType(mat, 1); 8019 MatCheckPreallocated(mat, 1); 8020 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8021 if (!mat->ops->residual) { 8022 PetscCall(MatMult(mat, x, r)); 8023 PetscCall(VecAYPX(r, -1.0, b)); 8024 } else { 8025 PetscUseTypeMethod(mat, residual, b, x, r); 8026 } 8027 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8028 PetscFunctionReturn(PETSC_SUCCESS); 8029 } 8030 8031 /*@C 8032 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8033 8034 Collective 8035 8036 Input Parameters: 8037 + mat - the matrix 8038 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8039 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8040 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8041 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8042 always used. 8043 8044 Output Parameters: 8045 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8046 . 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 8047 . ja - the column indices, use `NULL` if not needed 8048 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8049 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8050 8051 Level: developer 8052 8053 Notes: 8054 You CANNOT change any of the ia[] or ja[] values. 8055 8056 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8057 8058 Fortran Notes: 8059 Use 8060 .vb 8061 PetscInt, pointer :: ia(:),ja(:) 8062 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8063 ! Access the ith and jth entries via ia(i) and ja(j) 8064 .ve 8065 8066 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8067 @*/ 8068 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8069 { 8070 PetscFunctionBegin; 8071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8072 PetscValidType(mat, 1); 8073 if (n) PetscAssertPointer(n, 5); 8074 if (ia) PetscAssertPointer(ia, 6); 8075 if (ja) PetscAssertPointer(ja, 7); 8076 if (done) PetscAssertPointer(done, 8); 8077 MatCheckPreallocated(mat, 1); 8078 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8079 else { 8080 if (done) *done = PETSC_TRUE; 8081 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8082 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8083 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8084 } 8085 PetscFunctionReturn(PETSC_SUCCESS); 8086 } 8087 8088 /*@C 8089 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8090 8091 Collective 8092 8093 Input Parameters: 8094 + mat - the matrix 8095 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8096 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8097 symmetrized 8098 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8099 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8100 always used. 8101 . n - number of columns in the (possibly compressed) matrix 8102 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8103 - ja - the row indices 8104 8105 Output Parameter: 8106 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8107 8108 Level: developer 8109 8110 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8111 @*/ 8112 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8113 { 8114 PetscFunctionBegin; 8115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8116 PetscValidType(mat, 1); 8117 PetscAssertPointer(n, 5); 8118 if (ia) PetscAssertPointer(ia, 6); 8119 if (ja) PetscAssertPointer(ja, 7); 8120 PetscAssertPointer(done, 8); 8121 MatCheckPreallocated(mat, 1); 8122 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8123 else { 8124 *done = PETSC_TRUE; 8125 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8126 } 8127 PetscFunctionReturn(PETSC_SUCCESS); 8128 } 8129 8130 /*@C 8131 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8132 8133 Collective 8134 8135 Input Parameters: 8136 + mat - the matrix 8137 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8138 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8139 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8140 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8141 always used. 8142 . n - size of (possibly compressed) matrix 8143 . ia - the row pointers 8144 - ja - the column indices 8145 8146 Output Parameter: 8147 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8148 8149 Level: developer 8150 8151 Note: 8152 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8153 us of the array after it has been restored. If you pass `NULL`, it will 8154 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8155 8156 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8157 @*/ 8158 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8159 { 8160 PetscFunctionBegin; 8161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8162 PetscValidType(mat, 1); 8163 if (ia) PetscAssertPointer(ia, 6); 8164 if (ja) PetscAssertPointer(ja, 7); 8165 if (done) PetscAssertPointer(done, 8); 8166 MatCheckPreallocated(mat, 1); 8167 8168 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8169 else { 8170 if (done) *done = PETSC_TRUE; 8171 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8172 if (n) *n = 0; 8173 if (ia) *ia = NULL; 8174 if (ja) *ja = NULL; 8175 } 8176 PetscFunctionReturn(PETSC_SUCCESS); 8177 } 8178 8179 /*@C 8180 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8181 8182 Collective 8183 8184 Input Parameters: 8185 + mat - the matrix 8186 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8187 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8188 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8189 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8190 always used. 8191 8192 Output Parameters: 8193 + n - size of (possibly compressed) matrix 8194 . ia - the column pointers 8195 . ja - the row indices 8196 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8197 8198 Level: developer 8199 8200 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8201 @*/ 8202 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8203 { 8204 PetscFunctionBegin; 8205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8206 PetscValidType(mat, 1); 8207 if (ia) PetscAssertPointer(ia, 6); 8208 if (ja) PetscAssertPointer(ja, 7); 8209 PetscAssertPointer(done, 8); 8210 MatCheckPreallocated(mat, 1); 8211 8212 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8213 else { 8214 *done = PETSC_TRUE; 8215 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8216 if (n) *n = 0; 8217 if (ia) *ia = NULL; 8218 if (ja) *ja = NULL; 8219 } 8220 PetscFunctionReturn(PETSC_SUCCESS); 8221 } 8222 8223 /*@ 8224 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8225 `MatGetColumnIJ()`. 8226 8227 Collective 8228 8229 Input Parameters: 8230 + mat - the matrix 8231 . ncolors - maximum color value 8232 . n - number of entries in colorarray 8233 - colorarray - array indicating color for each column 8234 8235 Output Parameter: 8236 . iscoloring - coloring generated using colorarray information 8237 8238 Level: developer 8239 8240 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8241 @*/ 8242 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8243 { 8244 PetscFunctionBegin; 8245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8246 PetscValidType(mat, 1); 8247 PetscAssertPointer(colorarray, 4); 8248 PetscAssertPointer(iscoloring, 5); 8249 MatCheckPreallocated(mat, 1); 8250 8251 if (!mat->ops->coloringpatch) { 8252 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8253 } else { 8254 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8255 } 8256 PetscFunctionReturn(PETSC_SUCCESS); 8257 } 8258 8259 /*@ 8260 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8261 8262 Logically Collective 8263 8264 Input Parameter: 8265 . mat - the factored matrix to be reset 8266 8267 Level: developer 8268 8269 Notes: 8270 This routine should be used only with factored matrices formed by in-place 8271 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8272 format). This option can save memory, for example, when solving nonlinear 8273 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8274 ILU(0) preconditioner. 8275 8276 One can specify in-place ILU(0) factorization by calling 8277 .vb 8278 PCType(pc,PCILU); 8279 PCFactorSeUseInPlace(pc); 8280 .ve 8281 or by using the options -pc_type ilu -pc_factor_in_place 8282 8283 In-place factorization ILU(0) can also be used as a local 8284 solver for the blocks within the block Jacobi or additive Schwarz 8285 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8286 for details on setting local solver options. 8287 8288 Most users should employ the `KSP` interface for linear solvers 8289 instead of working directly with matrix algebra routines such as this. 8290 See, e.g., `KSPCreate()`. 8291 8292 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8293 @*/ 8294 PetscErrorCode MatSetUnfactored(Mat mat) 8295 { 8296 PetscFunctionBegin; 8297 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8298 PetscValidType(mat, 1); 8299 MatCheckPreallocated(mat, 1); 8300 mat->factortype = MAT_FACTOR_NONE; 8301 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8302 PetscUseTypeMethod(mat, setunfactored); 8303 PetscFunctionReturn(PETSC_SUCCESS); 8304 } 8305 8306 /*@ 8307 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8308 as the original matrix. 8309 8310 Collective 8311 8312 Input Parameters: 8313 + mat - the original matrix 8314 . isrow - parallel `IS` containing the rows this processor should obtain 8315 . 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. 8316 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8317 8318 Output Parameter: 8319 . newmat - the new submatrix, of the same type as the original matrix 8320 8321 Level: advanced 8322 8323 Notes: 8324 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8325 8326 Some matrix types place restrictions on the row and column indices, such 8327 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; 8328 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8329 8330 The index sets may not have duplicate entries. 8331 8332 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8333 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8334 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8335 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8336 you are finished using it. 8337 8338 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8339 the input matrix. 8340 8341 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8342 8343 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8344 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8345 8346 Example usage: 8347 Consider the following 8x8 matrix with 34 non-zero values, that is 8348 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8349 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8350 as follows 8351 .vb 8352 1 2 0 | 0 3 0 | 0 4 8353 Proc0 0 5 6 | 7 0 0 | 8 0 8354 9 0 10 | 11 0 0 | 12 0 8355 ------------------------------------- 8356 13 0 14 | 15 16 17 | 0 0 8357 Proc1 0 18 0 | 19 20 21 | 0 0 8358 0 0 0 | 22 23 0 | 24 0 8359 ------------------------------------- 8360 Proc2 25 26 27 | 0 0 28 | 29 0 8361 30 0 0 | 31 32 33 | 0 34 8362 .ve 8363 8364 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8365 8366 .vb 8367 2 0 | 0 3 0 | 0 8368 Proc0 5 6 | 7 0 0 | 8 8369 ------------------------------- 8370 Proc1 18 0 | 19 20 21 | 0 8371 ------------------------------- 8372 Proc2 26 27 | 0 0 28 | 29 8373 0 0 | 31 32 33 | 0 8374 .ve 8375 8376 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8377 @*/ 8378 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8379 { 8380 PetscMPIInt size; 8381 Mat *local; 8382 IS iscoltmp; 8383 PetscBool flg; 8384 8385 PetscFunctionBegin; 8386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8387 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8388 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8389 PetscAssertPointer(newmat, 5); 8390 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8391 PetscValidType(mat, 1); 8392 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8393 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8394 8395 MatCheckPreallocated(mat, 1); 8396 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8397 8398 if (!iscol || isrow == iscol) { 8399 PetscBool stride; 8400 PetscMPIInt grabentirematrix = 0, grab; 8401 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8402 if (stride) { 8403 PetscInt first, step, n, rstart, rend; 8404 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8405 if (step == 1) { 8406 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8407 if (rstart == first) { 8408 PetscCall(ISGetLocalSize(isrow, &n)); 8409 if (n == rend - rstart) grabentirematrix = 1; 8410 } 8411 } 8412 } 8413 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8414 if (grab) { 8415 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8416 if (cll == MAT_INITIAL_MATRIX) { 8417 *newmat = mat; 8418 PetscCall(PetscObjectReference((PetscObject)mat)); 8419 } 8420 PetscFunctionReturn(PETSC_SUCCESS); 8421 } 8422 } 8423 8424 if (!iscol) { 8425 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8426 } else { 8427 iscoltmp = iscol; 8428 } 8429 8430 /* if original matrix is on just one processor then use submatrix generated */ 8431 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8432 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8433 goto setproperties; 8434 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8435 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8436 *newmat = *local; 8437 PetscCall(PetscFree(local)); 8438 goto setproperties; 8439 } else if (!mat->ops->createsubmatrix) { 8440 /* Create a new matrix type that implements the operation using the full matrix */ 8441 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8442 switch (cll) { 8443 case MAT_INITIAL_MATRIX: 8444 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8445 break; 8446 case MAT_REUSE_MATRIX: 8447 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8448 break; 8449 default: 8450 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8451 } 8452 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8453 goto setproperties; 8454 } 8455 8456 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8457 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8458 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8459 8460 setproperties: 8461 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8462 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8463 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8464 } 8465 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8466 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8467 PetscFunctionReturn(PETSC_SUCCESS); 8468 } 8469 8470 /*@ 8471 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8472 8473 Not Collective 8474 8475 Input Parameters: 8476 + A - the matrix we wish to propagate options from 8477 - B - the matrix we wish to propagate options to 8478 8479 Level: beginner 8480 8481 Note: 8482 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8483 8484 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8485 @*/ 8486 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8487 { 8488 PetscFunctionBegin; 8489 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8490 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8491 B->symmetry_eternal = A->symmetry_eternal; 8492 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8493 B->symmetric = A->symmetric; 8494 B->structurally_symmetric = A->structurally_symmetric; 8495 B->spd = A->spd; 8496 B->hermitian = A->hermitian; 8497 PetscFunctionReturn(PETSC_SUCCESS); 8498 } 8499 8500 /*@ 8501 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8502 used during the assembly process to store values that belong to 8503 other processors. 8504 8505 Not Collective 8506 8507 Input Parameters: 8508 + mat - the matrix 8509 . size - the initial size of the stash. 8510 - bsize - the initial size of the block-stash(if used). 8511 8512 Options Database Keys: 8513 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8514 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8515 8516 Level: intermediate 8517 8518 Notes: 8519 The block-stash is used for values set with `MatSetValuesBlocked()` while 8520 the stash is used for values set with `MatSetValues()` 8521 8522 Run with the option -info and look for output of the form 8523 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8524 to determine the appropriate value, MM, to use for size and 8525 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8526 to determine the value, BMM to use for bsize 8527 8528 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8529 @*/ 8530 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8531 { 8532 PetscFunctionBegin; 8533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8534 PetscValidType(mat, 1); 8535 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8536 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8537 PetscFunctionReturn(PETSC_SUCCESS); 8538 } 8539 8540 /*@ 8541 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8542 the matrix 8543 8544 Neighbor-wise Collective 8545 8546 Input Parameters: 8547 + A - the matrix 8548 . x - the vector to be multiplied by the interpolation operator 8549 - y - the vector to be added to the result 8550 8551 Output Parameter: 8552 . w - the resulting vector 8553 8554 Level: intermediate 8555 8556 Notes: 8557 `w` may be the same vector as `y`. 8558 8559 This allows one to use either the restriction or interpolation (its transpose) 8560 matrix to do the interpolation 8561 8562 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8563 @*/ 8564 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8565 { 8566 PetscInt M, N, Ny; 8567 8568 PetscFunctionBegin; 8569 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8570 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8571 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8572 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8573 PetscCall(MatGetSize(A, &M, &N)); 8574 PetscCall(VecGetSize(y, &Ny)); 8575 if (M == Ny) { 8576 PetscCall(MatMultAdd(A, x, y, w)); 8577 } else { 8578 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8579 } 8580 PetscFunctionReturn(PETSC_SUCCESS); 8581 } 8582 8583 /*@ 8584 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8585 the matrix 8586 8587 Neighbor-wise Collective 8588 8589 Input Parameters: 8590 + A - the matrix 8591 - x - the vector to be interpolated 8592 8593 Output Parameter: 8594 . y - the resulting vector 8595 8596 Level: intermediate 8597 8598 Note: 8599 This allows one to use either the restriction or interpolation (its transpose) 8600 matrix to do the interpolation 8601 8602 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8603 @*/ 8604 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8605 { 8606 PetscInt M, N, Ny; 8607 8608 PetscFunctionBegin; 8609 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8610 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8611 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8612 PetscCall(MatGetSize(A, &M, &N)); 8613 PetscCall(VecGetSize(y, &Ny)); 8614 if (M == Ny) { 8615 PetscCall(MatMult(A, x, y)); 8616 } else { 8617 PetscCall(MatMultTranspose(A, x, y)); 8618 } 8619 PetscFunctionReturn(PETSC_SUCCESS); 8620 } 8621 8622 /*@ 8623 MatRestrict - $y = A*x$ or $A^T*x$ 8624 8625 Neighbor-wise Collective 8626 8627 Input Parameters: 8628 + A - the matrix 8629 - x - the vector to be restricted 8630 8631 Output Parameter: 8632 . y - the resulting vector 8633 8634 Level: intermediate 8635 8636 Note: 8637 This allows one to use either the restriction or interpolation (its transpose) 8638 matrix to do the restriction 8639 8640 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8641 @*/ 8642 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8643 { 8644 PetscInt M, N, Nx; 8645 8646 PetscFunctionBegin; 8647 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8648 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8649 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8650 PetscCall(MatGetSize(A, &M, &N)); 8651 PetscCall(VecGetSize(x, &Nx)); 8652 if (M == Nx) { 8653 PetscCall(MatMultTranspose(A, x, y)); 8654 } else { 8655 PetscCall(MatMult(A, x, y)); 8656 } 8657 PetscFunctionReturn(PETSC_SUCCESS); 8658 } 8659 8660 /*@ 8661 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8662 8663 Neighbor-wise Collective 8664 8665 Input Parameters: 8666 + A - the matrix 8667 . x - the input dense matrix to be multiplied 8668 - w - the input dense matrix to be added to the result 8669 8670 Output Parameter: 8671 . y - the output dense matrix 8672 8673 Level: intermediate 8674 8675 Note: 8676 This allows one to use either the restriction or interpolation (its transpose) 8677 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8678 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8679 8680 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8681 @*/ 8682 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8683 { 8684 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8685 PetscBool trans = PETSC_TRUE; 8686 MatReuse reuse = MAT_INITIAL_MATRIX; 8687 8688 PetscFunctionBegin; 8689 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8690 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8691 PetscValidType(x, 2); 8692 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8693 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8694 PetscCall(MatGetSize(A, &M, &N)); 8695 PetscCall(MatGetSize(x, &Mx, &Nx)); 8696 if (N == Mx) trans = PETSC_FALSE; 8697 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); 8698 Mo = trans ? N : M; 8699 if (*y) { 8700 PetscCall(MatGetSize(*y, &My, &Ny)); 8701 if (Mo == My && Nx == Ny) { 8702 reuse = MAT_REUSE_MATRIX; 8703 } else { 8704 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); 8705 PetscCall(MatDestroy(y)); 8706 } 8707 } 8708 8709 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8710 PetscBool flg; 8711 8712 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8713 if (w) { 8714 PetscInt My, Ny, Mw, Nw; 8715 8716 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8717 PetscCall(MatGetSize(*y, &My, &Ny)); 8718 PetscCall(MatGetSize(w, &Mw, &Nw)); 8719 if (!flg || My != Mw || Ny != Nw) w = NULL; 8720 } 8721 if (!w) { 8722 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8723 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8724 PetscCall(PetscObjectDereference((PetscObject)w)); 8725 } else { 8726 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8727 } 8728 } 8729 if (!trans) { 8730 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8731 } else { 8732 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8733 } 8734 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8735 PetscFunctionReturn(PETSC_SUCCESS); 8736 } 8737 8738 /*@ 8739 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8740 8741 Neighbor-wise Collective 8742 8743 Input Parameters: 8744 + A - the matrix 8745 - x - the input dense matrix 8746 8747 Output Parameter: 8748 . y - the output dense matrix 8749 8750 Level: intermediate 8751 8752 Note: 8753 This allows one to use either the restriction or interpolation (its transpose) 8754 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8755 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8756 8757 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8758 @*/ 8759 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8760 { 8761 PetscFunctionBegin; 8762 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8763 PetscFunctionReturn(PETSC_SUCCESS); 8764 } 8765 8766 /*@ 8767 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8768 8769 Neighbor-wise Collective 8770 8771 Input Parameters: 8772 + A - the matrix 8773 - x - the input dense matrix 8774 8775 Output Parameter: 8776 . y - the output dense matrix 8777 8778 Level: intermediate 8779 8780 Note: 8781 This allows one to use either the restriction or interpolation (its transpose) 8782 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8783 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8784 8785 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8786 @*/ 8787 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8788 { 8789 PetscFunctionBegin; 8790 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8791 PetscFunctionReturn(PETSC_SUCCESS); 8792 } 8793 8794 /*@ 8795 MatGetNullSpace - retrieves the null space of a matrix. 8796 8797 Logically Collective 8798 8799 Input Parameters: 8800 + mat - the matrix 8801 - nullsp - the null space object 8802 8803 Level: developer 8804 8805 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8806 @*/ 8807 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8808 { 8809 PetscFunctionBegin; 8810 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8811 PetscAssertPointer(nullsp, 2); 8812 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8813 PetscFunctionReturn(PETSC_SUCCESS); 8814 } 8815 8816 /*@C 8817 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8818 8819 Logically Collective 8820 8821 Input Parameters: 8822 + n - the number of matrices 8823 - mat - the array of matrices 8824 8825 Output Parameters: 8826 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8827 8828 Level: developer 8829 8830 Note: 8831 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8832 8833 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8834 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8835 @*/ 8836 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8837 { 8838 PetscFunctionBegin; 8839 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8840 PetscAssertPointer(mat, 2); 8841 PetscAssertPointer(nullsp, 3); 8842 8843 PetscCall(PetscCalloc1(3 * n, nullsp)); 8844 for (PetscInt i = 0; i < n; i++) { 8845 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8846 (*nullsp)[i] = mat[i]->nullsp; 8847 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8848 (*nullsp)[n + i] = mat[i]->nearnullsp; 8849 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8850 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8851 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8852 } 8853 PetscFunctionReturn(PETSC_SUCCESS); 8854 } 8855 8856 /*@C 8857 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8858 8859 Logically Collective 8860 8861 Input Parameters: 8862 + n - the number of matrices 8863 . mat - the array of matrices 8864 - nullsp - an array of null spaces 8865 8866 Level: developer 8867 8868 Note: 8869 Call `MatGetNullSpaces()` to create `nullsp` 8870 8871 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8872 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8873 @*/ 8874 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8875 { 8876 PetscFunctionBegin; 8877 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8878 PetscAssertPointer(mat, 2); 8879 PetscAssertPointer(nullsp, 3); 8880 PetscAssertPointer(*nullsp, 3); 8881 8882 for (PetscInt i = 0; i < n; i++) { 8883 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8884 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8885 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8886 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8887 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8888 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8889 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8890 } 8891 PetscCall(PetscFree(*nullsp)); 8892 PetscFunctionReturn(PETSC_SUCCESS); 8893 } 8894 8895 /*@ 8896 MatSetNullSpace - attaches a null space to a matrix. 8897 8898 Logically Collective 8899 8900 Input Parameters: 8901 + mat - the matrix 8902 - nullsp - the null space object 8903 8904 Level: advanced 8905 8906 Notes: 8907 This null space is used by the `KSP` linear solvers to solve singular systems. 8908 8909 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` 8910 8911 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 8912 to zero but the linear system will still be solved in a least squares sense. 8913 8914 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8915 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)$. 8916 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 8917 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 8918 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$). 8919 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8920 8921 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8922 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8923 routine also automatically calls `MatSetTransposeNullSpace()`. 8924 8925 The user should call `MatNullSpaceDestroy()`. 8926 8927 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8928 `KSPSetPCSide()` 8929 @*/ 8930 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8931 { 8932 PetscFunctionBegin; 8933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8934 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8935 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8936 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8937 mat->nullsp = nullsp; 8938 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8939 PetscFunctionReturn(PETSC_SUCCESS); 8940 } 8941 8942 /*@ 8943 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8944 8945 Logically Collective 8946 8947 Input Parameters: 8948 + mat - the matrix 8949 - nullsp - the null space object 8950 8951 Level: developer 8952 8953 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8954 @*/ 8955 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8956 { 8957 PetscFunctionBegin; 8958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8959 PetscValidType(mat, 1); 8960 PetscAssertPointer(nullsp, 2); 8961 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8962 PetscFunctionReturn(PETSC_SUCCESS); 8963 } 8964 8965 /*@ 8966 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8967 8968 Logically Collective 8969 8970 Input Parameters: 8971 + mat - the matrix 8972 - nullsp - the null space object 8973 8974 Level: advanced 8975 8976 Notes: 8977 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8978 8979 See `MatSetNullSpace()` 8980 8981 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8982 @*/ 8983 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8984 { 8985 PetscFunctionBegin; 8986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8987 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8988 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8989 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8990 mat->transnullsp = nullsp; 8991 PetscFunctionReturn(PETSC_SUCCESS); 8992 } 8993 8994 /*@ 8995 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8996 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this 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 Overwrites any previous near null space that may have been attached 9008 9009 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9010 9011 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9012 @*/ 9013 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9014 { 9015 PetscFunctionBegin; 9016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9017 PetscValidType(mat, 1); 9018 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9019 MatCheckPreallocated(mat, 1); 9020 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9021 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9022 mat->nearnullsp = nullsp; 9023 PetscFunctionReturn(PETSC_SUCCESS); 9024 } 9025 9026 /*@ 9027 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9028 9029 Not Collective 9030 9031 Input Parameter: 9032 . mat - the matrix 9033 9034 Output Parameter: 9035 . nullsp - the null space object, `NULL` if not set 9036 9037 Level: advanced 9038 9039 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9040 @*/ 9041 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9042 { 9043 PetscFunctionBegin; 9044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9045 PetscValidType(mat, 1); 9046 PetscAssertPointer(nullsp, 2); 9047 MatCheckPreallocated(mat, 1); 9048 *nullsp = mat->nearnullsp; 9049 PetscFunctionReturn(PETSC_SUCCESS); 9050 } 9051 9052 /*@ 9053 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9054 9055 Collective 9056 9057 Input Parameters: 9058 + mat - the matrix 9059 . row - row/column permutation 9060 - info - information on desired factorization process 9061 9062 Level: developer 9063 9064 Notes: 9065 Probably really in-place only when level of fill is zero, otherwise allocates 9066 new space to store factored matrix and deletes previous memory. 9067 9068 Most users should employ the `KSP` interface for linear solvers 9069 instead of working directly with matrix algebra routines such as this. 9070 See, e.g., `KSPCreate()`. 9071 9072 Fortran Note: 9073 A valid (non-null) `info` argument must be provided 9074 9075 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9076 @*/ 9077 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9078 { 9079 PetscFunctionBegin; 9080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9081 PetscValidType(mat, 1); 9082 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9083 PetscAssertPointer(info, 3); 9084 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9085 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9086 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9087 MatCheckPreallocated(mat, 1); 9088 PetscUseTypeMethod(mat, iccfactor, row, info); 9089 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9090 PetscFunctionReturn(PETSC_SUCCESS); 9091 } 9092 9093 /*@ 9094 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9095 ghosted ones. 9096 9097 Not Collective 9098 9099 Input Parameters: 9100 + mat - the matrix 9101 - diag - the diagonal values, including ghost ones 9102 9103 Level: developer 9104 9105 Notes: 9106 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9107 9108 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9109 9110 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9111 @*/ 9112 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9113 { 9114 PetscMPIInt size; 9115 9116 PetscFunctionBegin; 9117 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9118 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9119 PetscValidType(mat, 1); 9120 9121 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9122 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9123 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9124 if (size == 1) { 9125 PetscInt n, m; 9126 PetscCall(VecGetSize(diag, &n)); 9127 PetscCall(MatGetSize(mat, NULL, &m)); 9128 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9129 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9130 } else { 9131 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9132 } 9133 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9134 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9135 PetscFunctionReturn(PETSC_SUCCESS); 9136 } 9137 9138 /*@ 9139 MatGetInertia - Gets the inertia from a factored matrix 9140 9141 Collective 9142 9143 Input Parameter: 9144 . mat - the matrix 9145 9146 Output Parameters: 9147 + nneg - number of negative eigenvalues 9148 . nzero - number of zero eigenvalues 9149 - npos - number of positive eigenvalues 9150 9151 Level: advanced 9152 9153 Note: 9154 Matrix must have been factored by `MatCholeskyFactor()` 9155 9156 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9157 @*/ 9158 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9159 { 9160 PetscFunctionBegin; 9161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9162 PetscValidType(mat, 1); 9163 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9164 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9165 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9166 PetscFunctionReturn(PETSC_SUCCESS); 9167 } 9168 9169 /*@C 9170 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9171 9172 Neighbor-wise Collective 9173 9174 Input Parameters: 9175 + mat - the factored matrix obtained with `MatGetFactor()` 9176 - b - the right-hand-side vectors 9177 9178 Output Parameter: 9179 . x - the result vectors 9180 9181 Level: developer 9182 9183 Note: 9184 The vectors `b` and `x` cannot be the same. I.e., one cannot 9185 call `MatSolves`(A,x,x). 9186 9187 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9188 @*/ 9189 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9190 { 9191 PetscFunctionBegin; 9192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9193 PetscValidType(mat, 1); 9194 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9195 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9196 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9197 9198 MatCheckPreallocated(mat, 1); 9199 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9200 PetscUseTypeMethod(mat, solves, b, x); 9201 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9202 PetscFunctionReturn(PETSC_SUCCESS); 9203 } 9204 9205 /*@ 9206 MatIsSymmetric - Test whether a matrix is symmetric 9207 9208 Collective 9209 9210 Input Parameters: 9211 + A - the matrix to test 9212 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9213 9214 Output Parameter: 9215 . flg - the result 9216 9217 Level: intermediate 9218 9219 Notes: 9220 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9221 9222 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9223 9224 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9225 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9226 9227 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9228 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9229 @*/ 9230 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9231 { 9232 PetscFunctionBegin; 9233 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9234 PetscAssertPointer(flg, 3); 9235 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9236 else { 9237 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9238 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9239 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9240 } 9241 PetscFunctionReturn(PETSC_SUCCESS); 9242 } 9243 9244 /*@ 9245 MatIsHermitian - Test whether a matrix is Hermitian 9246 9247 Collective 9248 9249 Input Parameters: 9250 + A - the matrix to test 9251 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9252 9253 Output Parameter: 9254 . flg - the result 9255 9256 Level: intermediate 9257 9258 Notes: 9259 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9260 9261 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9262 9263 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9264 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9265 9266 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9267 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9268 @*/ 9269 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9270 { 9271 PetscFunctionBegin; 9272 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9273 PetscAssertPointer(flg, 3); 9274 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9275 else { 9276 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9277 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9278 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9279 } 9280 PetscFunctionReturn(PETSC_SUCCESS); 9281 } 9282 9283 /*@ 9284 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9285 9286 Not Collective 9287 9288 Input Parameter: 9289 . A - the matrix to check 9290 9291 Output Parameters: 9292 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9293 - flg - the result (only valid if set is `PETSC_TRUE`) 9294 9295 Level: advanced 9296 9297 Notes: 9298 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9299 if you want it explicitly checked 9300 9301 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9302 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9303 9304 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9305 @*/ 9306 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9307 { 9308 PetscFunctionBegin; 9309 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9310 PetscAssertPointer(set, 2); 9311 PetscAssertPointer(flg, 3); 9312 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9313 *set = PETSC_TRUE; 9314 *flg = PetscBool3ToBool(A->symmetric); 9315 } else { 9316 *set = PETSC_FALSE; 9317 } 9318 PetscFunctionReturn(PETSC_SUCCESS); 9319 } 9320 9321 /*@ 9322 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9323 9324 Not Collective 9325 9326 Input Parameter: 9327 . A - the matrix to check 9328 9329 Output Parameters: 9330 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9331 - flg - the result (only valid if set is `PETSC_TRUE`) 9332 9333 Level: advanced 9334 9335 Notes: 9336 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9337 9338 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9339 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9340 9341 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9342 @*/ 9343 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9344 { 9345 PetscFunctionBegin; 9346 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9347 PetscAssertPointer(set, 2); 9348 PetscAssertPointer(flg, 3); 9349 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9350 *set = PETSC_TRUE; 9351 *flg = PetscBool3ToBool(A->spd); 9352 } else { 9353 *set = PETSC_FALSE; 9354 } 9355 PetscFunctionReturn(PETSC_SUCCESS); 9356 } 9357 9358 /*@ 9359 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9360 9361 Not Collective 9362 9363 Input Parameter: 9364 . A - the matrix to check 9365 9366 Output Parameters: 9367 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9368 - flg - the result (only valid if set is `PETSC_TRUE`) 9369 9370 Level: advanced 9371 9372 Notes: 9373 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9374 if you want it explicitly checked 9375 9376 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9377 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9378 9379 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9380 @*/ 9381 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9382 { 9383 PetscFunctionBegin; 9384 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9385 PetscAssertPointer(set, 2); 9386 PetscAssertPointer(flg, 3); 9387 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9388 *set = PETSC_TRUE; 9389 *flg = PetscBool3ToBool(A->hermitian); 9390 } else { 9391 *set = PETSC_FALSE; 9392 } 9393 PetscFunctionReturn(PETSC_SUCCESS); 9394 } 9395 9396 /*@ 9397 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9398 9399 Collective 9400 9401 Input Parameter: 9402 . A - the matrix to test 9403 9404 Output Parameter: 9405 . flg - the result 9406 9407 Level: intermediate 9408 9409 Notes: 9410 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9411 9412 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 9413 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9414 9415 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9416 @*/ 9417 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9418 { 9419 PetscFunctionBegin; 9420 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9421 PetscAssertPointer(flg, 2); 9422 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9423 *flg = PetscBool3ToBool(A->structurally_symmetric); 9424 } else { 9425 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9426 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9427 } 9428 PetscFunctionReturn(PETSC_SUCCESS); 9429 } 9430 9431 /*@ 9432 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9433 9434 Not Collective 9435 9436 Input Parameter: 9437 . A - the matrix to check 9438 9439 Output Parameters: 9440 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9441 - flg - the result (only valid if set is PETSC_TRUE) 9442 9443 Level: advanced 9444 9445 Notes: 9446 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 9447 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9448 9449 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9450 9451 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9452 @*/ 9453 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9454 { 9455 PetscFunctionBegin; 9456 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9457 PetscAssertPointer(set, 2); 9458 PetscAssertPointer(flg, 3); 9459 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9460 *set = PETSC_TRUE; 9461 *flg = PetscBool3ToBool(A->structurally_symmetric); 9462 } else { 9463 *set = PETSC_FALSE; 9464 } 9465 PetscFunctionReturn(PETSC_SUCCESS); 9466 } 9467 9468 /*@ 9469 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9470 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9471 9472 Not Collective 9473 9474 Input Parameter: 9475 . mat - the matrix 9476 9477 Output Parameters: 9478 + nstash - the size of the stash 9479 . reallocs - the number of additional mallocs incurred. 9480 . bnstash - the size of the block stash 9481 - breallocs - the number of additional mallocs incurred.in the block stash 9482 9483 Level: advanced 9484 9485 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9486 @*/ 9487 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9488 { 9489 PetscFunctionBegin; 9490 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9491 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9492 PetscFunctionReturn(PETSC_SUCCESS); 9493 } 9494 9495 /*@ 9496 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9497 parallel layout, `PetscLayout` for rows and columns 9498 9499 Collective 9500 9501 Input Parameter: 9502 . mat - the matrix 9503 9504 Output Parameters: 9505 + right - (optional) vector that the matrix can be multiplied against 9506 - left - (optional) vector that the matrix vector product can be stored in 9507 9508 Level: advanced 9509 9510 Notes: 9511 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()`. 9512 9513 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9514 9515 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9516 @*/ 9517 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9518 { 9519 PetscFunctionBegin; 9520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9521 PetscValidType(mat, 1); 9522 if (mat->ops->getvecs) { 9523 PetscUseTypeMethod(mat, getvecs, right, left); 9524 } else { 9525 if (right) { 9526 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9527 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9528 PetscCall(VecSetType(*right, mat->defaultvectype)); 9529 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9530 if (mat->boundtocpu && mat->bindingpropagates) { 9531 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9532 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9533 } 9534 #endif 9535 } 9536 if (left) { 9537 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9538 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9539 PetscCall(VecSetType(*left, mat->defaultvectype)); 9540 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9541 if (mat->boundtocpu && mat->bindingpropagates) { 9542 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9543 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9544 } 9545 #endif 9546 } 9547 } 9548 PetscFunctionReturn(PETSC_SUCCESS); 9549 } 9550 9551 /*@ 9552 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9553 with default values. 9554 9555 Not Collective 9556 9557 Input Parameter: 9558 . info - the `MatFactorInfo` data structure 9559 9560 Level: developer 9561 9562 Notes: 9563 The solvers are generally used through the `KSP` and `PC` objects, for example 9564 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9565 9566 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9567 9568 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9569 @*/ 9570 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9571 { 9572 PetscFunctionBegin; 9573 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9574 PetscFunctionReturn(PETSC_SUCCESS); 9575 } 9576 9577 /*@ 9578 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9579 9580 Collective 9581 9582 Input Parameters: 9583 + mat - the factored matrix 9584 - is - the index set defining the Schur indices (0-based) 9585 9586 Level: advanced 9587 9588 Notes: 9589 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9590 9591 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9592 9593 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9594 9595 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9596 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9597 @*/ 9598 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9599 { 9600 PetscErrorCode (*f)(Mat, IS); 9601 9602 PetscFunctionBegin; 9603 PetscValidType(mat, 1); 9604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9605 PetscValidType(is, 2); 9606 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9607 PetscCheckSameComm(mat, 1, is, 2); 9608 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9609 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9610 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9611 PetscCall(MatDestroy(&mat->schur)); 9612 PetscCall((*f)(mat, is)); 9613 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9614 PetscFunctionReturn(PETSC_SUCCESS); 9615 } 9616 9617 /*@ 9618 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9619 9620 Logically Collective 9621 9622 Input Parameters: 9623 + F - the factored matrix obtained by calling `MatGetFactor()` 9624 . S - location where to return the Schur complement, can be `NULL` 9625 - status - the status of the Schur complement matrix, can be `NULL` 9626 9627 Level: advanced 9628 9629 Notes: 9630 You must call `MatFactorSetSchurIS()` before calling this routine. 9631 9632 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9633 9634 The routine provides a copy of the Schur matrix stored within the solver data structures. 9635 The caller must destroy the object when it is no longer needed. 9636 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9637 9638 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) 9639 9640 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9641 9642 Developer Note: 9643 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9644 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9645 9646 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9647 @*/ 9648 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9649 { 9650 PetscFunctionBegin; 9651 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9652 if (S) PetscAssertPointer(S, 2); 9653 if (status) PetscAssertPointer(status, 3); 9654 if (S) { 9655 PetscErrorCode (*f)(Mat, Mat *); 9656 9657 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9658 if (f) { 9659 PetscCall((*f)(F, S)); 9660 } else { 9661 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9662 } 9663 } 9664 if (status) *status = F->schur_status; 9665 PetscFunctionReturn(PETSC_SUCCESS); 9666 } 9667 9668 /*@ 9669 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9670 9671 Logically Collective 9672 9673 Input Parameters: 9674 + F - the factored matrix obtained by calling `MatGetFactor()` 9675 . S - location where to return the Schur complement, can be `NULL` 9676 - status - the status of the Schur complement matrix, can be `NULL` 9677 9678 Level: advanced 9679 9680 Notes: 9681 You must call `MatFactorSetSchurIS()` before calling this routine. 9682 9683 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9684 9685 The routine returns a the Schur Complement stored within the data structures of the solver. 9686 9687 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9688 9689 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9690 9691 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9692 9693 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9694 9695 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9696 @*/ 9697 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9698 { 9699 PetscFunctionBegin; 9700 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9701 if (S) { 9702 PetscAssertPointer(S, 2); 9703 *S = F->schur; 9704 } 9705 if (status) { 9706 PetscAssertPointer(status, 3); 9707 *status = F->schur_status; 9708 } 9709 PetscFunctionReturn(PETSC_SUCCESS); 9710 } 9711 9712 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9713 { 9714 Mat S = F->schur; 9715 9716 PetscFunctionBegin; 9717 switch (F->schur_status) { 9718 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9719 case MAT_FACTOR_SCHUR_INVERTED: 9720 if (S) { 9721 S->ops->solve = NULL; 9722 S->ops->matsolve = NULL; 9723 S->ops->solvetranspose = NULL; 9724 S->ops->matsolvetranspose = NULL; 9725 S->ops->solveadd = NULL; 9726 S->ops->solvetransposeadd = NULL; 9727 S->factortype = MAT_FACTOR_NONE; 9728 PetscCall(PetscFree(S->solvertype)); 9729 } 9730 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9731 break; 9732 default: 9733 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9734 } 9735 PetscFunctionReturn(PETSC_SUCCESS); 9736 } 9737 9738 /*@ 9739 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9740 9741 Logically Collective 9742 9743 Input Parameters: 9744 + F - the factored matrix obtained by calling `MatGetFactor()` 9745 . S - location where the Schur complement is stored 9746 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9747 9748 Level: advanced 9749 9750 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9751 @*/ 9752 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9753 { 9754 PetscFunctionBegin; 9755 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9756 if (S) { 9757 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9758 *S = NULL; 9759 } 9760 F->schur_status = status; 9761 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9762 PetscFunctionReturn(PETSC_SUCCESS); 9763 } 9764 9765 /*@ 9766 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9767 9768 Logically Collective 9769 9770 Input Parameters: 9771 + F - the factored matrix obtained by calling `MatGetFactor()` 9772 . rhs - location where the right-hand side of the Schur complement system is stored 9773 - sol - location where the solution of the Schur complement system has to be returned 9774 9775 Level: advanced 9776 9777 Notes: 9778 The sizes of the vectors should match the size of the Schur complement 9779 9780 Must be called after `MatFactorSetSchurIS()` 9781 9782 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9783 @*/ 9784 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9785 { 9786 PetscFunctionBegin; 9787 PetscValidType(F, 1); 9788 PetscValidType(rhs, 2); 9789 PetscValidType(sol, 3); 9790 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9791 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9792 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9793 PetscCheckSameComm(F, 1, rhs, 2); 9794 PetscCheckSameComm(F, 1, sol, 3); 9795 PetscCall(MatFactorFactorizeSchurComplement(F)); 9796 switch (F->schur_status) { 9797 case MAT_FACTOR_SCHUR_FACTORED: 9798 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9799 break; 9800 case MAT_FACTOR_SCHUR_INVERTED: 9801 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9802 break; 9803 default: 9804 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9805 } 9806 PetscFunctionReturn(PETSC_SUCCESS); 9807 } 9808 9809 /*@ 9810 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9811 9812 Logically Collective 9813 9814 Input Parameters: 9815 + F - the factored matrix obtained by calling `MatGetFactor()` 9816 . rhs - location where the right-hand side of the Schur complement system is stored 9817 - sol - location where the solution of the Schur complement system has to be returned 9818 9819 Level: advanced 9820 9821 Notes: 9822 The sizes of the vectors should match the size of the Schur complement 9823 9824 Must be called after `MatFactorSetSchurIS()` 9825 9826 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9827 @*/ 9828 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9829 { 9830 PetscFunctionBegin; 9831 PetscValidType(F, 1); 9832 PetscValidType(rhs, 2); 9833 PetscValidType(sol, 3); 9834 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9835 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9836 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9837 PetscCheckSameComm(F, 1, rhs, 2); 9838 PetscCheckSameComm(F, 1, sol, 3); 9839 PetscCall(MatFactorFactorizeSchurComplement(F)); 9840 switch (F->schur_status) { 9841 case MAT_FACTOR_SCHUR_FACTORED: 9842 PetscCall(MatSolve(F->schur, rhs, sol)); 9843 break; 9844 case MAT_FACTOR_SCHUR_INVERTED: 9845 PetscCall(MatMult(F->schur, rhs, sol)); 9846 break; 9847 default: 9848 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9849 } 9850 PetscFunctionReturn(PETSC_SUCCESS); 9851 } 9852 9853 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9854 #if PetscDefined(HAVE_CUDA) 9855 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9856 #endif 9857 9858 /* Schur status updated in the interface */ 9859 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9860 { 9861 Mat S = F->schur; 9862 9863 PetscFunctionBegin; 9864 if (S) { 9865 PetscMPIInt size; 9866 PetscBool isdense, isdensecuda; 9867 9868 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9869 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9870 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9871 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9872 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9873 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9874 if (isdense) { 9875 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9876 } else if (isdensecuda) { 9877 #if defined(PETSC_HAVE_CUDA) 9878 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9879 #endif 9880 } 9881 // HIP?????????????? 9882 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9883 } 9884 PetscFunctionReturn(PETSC_SUCCESS); 9885 } 9886 9887 /*@ 9888 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9889 9890 Logically Collective 9891 9892 Input Parameter: 9893 . F - the factored matrix obtained by calling `MatGetFactor()` 9894 9895 Level: advanced 9896 9897 Notes: 9898 Must be called after `MatFactorSetSchurIS()`. 9899 9900 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9901 9902 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9903 @*/ 9904 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9905 { 9906 PetscFunctionBegin; 9907 PetscValidType(F, 1); 9908 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9909 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9910 PetscCall(MatFactorFactorizeSchurComplement(F)); 9911 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9912 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9913 PetscFunctionReturn(PETSC_SUCCESS); 9914 } 9915 9916 /*@ 9917 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9918 9919 Logically Collective 9920 9921 Input Parameter: 9922 . F - the factored matrix obtained by calling `MatGetFactor()` 9923 9924 Level: advanced 9925 9926 Note: 9927 Must be called after `MatFactorSetSchurIS()` 9928 9929 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9930 @*/ 9931 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9932 { 9933 MatFactorInfo info; 9934 9935 PetscFunctionBegin; 9936 PetscValidType(F, 1); 9937 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9938 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9939 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9940 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9941 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9942 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9943 } else { 9944 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9945 } 9946 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9947 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9948 PetscFunctionReturn(PETSC_SUCCESS); 9949 } 9950 9951 /*@ 9952 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9953 9954 Neighbor-wise Collective 9955 9956 Input Parameters: 9957 + A - the matrix 9958 . P - the projection matrix 9959 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9960 - 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 9961 if the result is a dense matrix this is irrelevant 9962 9963 Output Parameter: 9964 . C - the product matrix 9965 9966 Level: intermediate 9967 9968 Notes: 9969 C will be created and must be destroyed by the user with `MatDestroy()`. 9970 9971 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9972 9973 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 9974 9975 Developer Note: 9976 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9977 9978 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9979 @*/ 9980 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9981 { 9982 PetscFunctionBegin; 9983 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9984 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9985 9986 if (scall == MAT_INITIAL_MATRIX) { 9987 PetscCall(MatProductCreate(A, P, NULL, C)); 9988 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9989 PetscCall(MatProductSetAlgorithm(*C, "default")); 9990 PetscCall(MatProductSetFill(*C, fill)); 9991 9992 (*C)->product->api_user = PETSC_TRUE; 9993 PetscCall(MatProductSetFromOptions(*C)); 9994 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); 9995 PetscCall(MatProductSymbolic(*C)); 9996 } else { /* scall == MAT_REUSE_MATRIX */ 9997 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9998 } 9999 10000 PetscCall(MatProductNumeric(*C)); 10001 (*C)->symmetric = A->symmetric; 10002 (*C)->spd = A->spd; 10003 PetscFunctionReturn(PETSC_SUCCESS); 10004 } 10005 10006 /*@ 10007 MatRARt - Creates the matrix product $C = R * A * R^T$ 10008 10009 Neighbor-wise Collective 10010 10011 Input Parameters: 10012 + A - the matrix 10013 . R - the projection matrix 10014 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10015 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10016 if the result is a dense matrix this is irrelevant 10017 10018 Output Parameter: 10019 . C - the product matrix 10020 10021 Level: intermediate 10022 10023 Notes: 10024 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10025 10026 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10027 10028 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10029 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10030 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10031 We recommend using `MatPtAP()` when possible. 10032 10033 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10034 10035 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10036 @*/ 10037 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10038 { 10039 PetscFunctionBegin; 10040 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10041 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10042 10043 if (scall == MAT_INITIAL_MATRIX) { 10044 PetscCall(MatProductCreate(A, R, NULL, C)); 10045 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10046 PetscCall(MatProductSetAlgorithm(*C, "default")); 10047 PetscCall(MatProductSetFill(*C, fill)); 10048 10049 (*C)->product->api_user = PETSC_TRUE; 10050 PetscCall(MatProductSetFromOptions(*C)); 10051 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); 10052 PetscCall(MatProductSymbolic(*C)); 10053 } else { /* scall == MAT_REUSE_MATRIX */ 10054 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10055 } 10056 10057 PetscCall(MatProductNumeric(*C)); 10058 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10059 PetscFunctionReturn(PETSC_SUCCESS); 10060 } 10061 10062 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10063 { 10064 PetscBool flg = PETSC_TRUE; 10065 10066 PetscFunctionBegin; 10067 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10068 if (scall == MAT_INITIAL_MATRIX) { 10069 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10070 PetscCall(MatProductCreate(A, B, NULL, C)); 10071 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10072 PetscCall(MatProductSetFill(*C, fill)); 10073 } else { /* scall == MAT_REUSE_MATRIX */ 10074 Mat_Product *product = (*C)->product; 10075 10076 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10077 if (flg && product && product->type != ptype) { 10078 PetscCall(MatProductClear(*C)); 10079 product = NULL; 10080 } 10081 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10082 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10083 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10084 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10085 product = (*C)->product; 10086 product->fill = fill; 10087 product->clear = PETSC_TRUE; 10088 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10089 flg = PETSC_FALSE; 10090 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10091 } 10092 } 10093 if (flg) { 10094 (*C)->product->api_user = PETSC_TRUE; 10095 PetscCall(MatProductSetType(*C, ptype)); 10096 PetscCall(MatProductSetFromOptions(*C)); 10097 PetscCall(MatProductSymbolic(*C)); 10098 } 10099 PetscCall(MatProductNumeric(*C)); 10100 PetscFunctionReturn(PETSC_SUCCESS); 10101 } 10102 10103 /*@ 10104 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10105 10106 Neighbor-wise Collective 10107 10108 Input Parameters: 10109 + A - the left matrix 10110 . B - the right matrix 10111 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10112 - 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 10113 if the result is a dense matrix this is irrelevant 10114 10115 Output Parameter: 10116 . C - the product matrix 10117 10118 Notes: 10119 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10120 10121 `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 10122 call to this function with `MAT_INITIAL_MATRIX`. 10123 10124 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10125 10126 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`, 10127 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10128 10129 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10130 10131 Example of Usage: 10132 .vb 10133 MatProductCreate(A,B,NULL,&C); 10134 MatProductSetType(C,MATPRODUCT_AB); 10135 MatProductSymbolic(C); 10136 MatProductNumeric(C); // compute C=A * B 10137 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10138 MatProductNumeric(C); 10139 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10140 MatProductNumeric(C); 10141 .ve 10142 10143 Level: intermediate 10144 10145 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10146 @*/ 10147 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10148 { 10149 PetscFunctionBegin; 10150 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10151 PetscFunctionReturn(PETSC_SUCCESS); 10152 } 10153 10154 /*@ 10155 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10156 10157 Neighbor-wise Collective 10158 10159 Input Parameters: 10160 + A - the left matrix 10161 . B - the right matrix 10162 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10163 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10164 10165 Output Parameter: 10166 . C - the product matrix 10167 10168 Options Database Key: 10169 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10170 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10171 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10172 10173 Level: intermediate 10174 10175 Notes: 10176 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10177 10178 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10179 10180 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10181 actually needed. 10182 10183 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10184 and for pairs of `MATMPIDENSE` matrices. 10185 10186 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10187 10188 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10189 10190 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10191 @*/ 10192 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10193 { 10194 PetscFunctionBegin; 10195 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10196 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10197 PetscFunctionReturn(PETSC_SUCCESS); 10198 } 10199 10200 /*@ 10201 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10202 10203 Neighbor-wise Collective 10204 10205 Input Parameters: 10206 + A - the left matrix 10207 . B - the right matrix 10208 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10209 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10210 10211 Output Parameter: 10212 . C - the product matrix 10213 10214 Level: intermediate 10215 10216 Notes: 10217 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10218 10219 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10220 10221 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10222 10223 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10224 actually needed. 10225 10226 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10227 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10228 10229 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10230 10231 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10232 @*/ 10233 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10234 { 10235 PetscFunctionBegin; 10236 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10237 PetscFunctionReturn(PETSC_SUCCESS); 10238 } 10239 10240 /*@ 10241 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10242 10243 Neighbor-wise Collective 10244 10245 Input Parameters: 10246 + A - the left matrix 10247 . B - the middle matrix 10248 . C - the right matrix 10249 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10250 - 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 10251 if the result is a dense matrix this is irrelevant 10252 10253 Output Parameter: 10254 . D - the product matrix 10255 10256 Level: intermediate 10257 10258 Notes: 10259 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10260 10261 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10262 10263 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10264 10265 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10266 actually needed. 10267 10268 If you have many matrices with the same non-zero structure to multiply, you 10269 should use `MAT_REUSE_MATRIX` in all calls but the first 10270 10271 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10272 10273 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10274 @*/ 10275 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10276 { 10277 PetscFunctionBegin; 10278 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10279 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10280 10281 if (scall == MAT_INITIAL_MATRIX) { 10282 PetscCall(MatProductCreate(A, B, C, D)); 10283 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10284 PetscCall(MatProductSetAlgorithm(*D, "default")); 10285 PetscCall(MatProductSetFill(*D, fill)); 10286 10287 (*D)->product->api_user = PETSC_TRUE; 10288 PetscCall(MatProductSetFromOptions(*D)); 10289 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, 10290 ((PetscObject)C)->type_name); 10291 PetscCall(MatProductSymbolic(*D)); 10292 } else { /* user may change input matrices when REUSE */ 10293 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10294 } 10295 PetscCall(MatProductNumeric(*D)); 10296 PetscFunctionReturn(PETSC_SUCCESS); 10297 } 10298 10299 /*@ 10300 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10301 10302 Collective 10303 10304 Input Parameters: 10305 + mat - the matrix 10306 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10307 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10308 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10309 10310 Output Parameter: 10311 . matredundant - redundant matrix 10312 10313 Level: advanced 10314 10315 Notes: 10316 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10317 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10318 10319 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10320 calling it. 10321 10322 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10323 10324 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10325 @*/ 10326 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10327 { 10328 MPI_Comm comm; 10329 PetscMPIInt size; 10330 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10331 Mat_Redundant *redund = NULL; 10332 PetscSubcomm psubcomm = NULL; 10333 MPI_Comm subcomm_in = subcomm; 10334 Mat *matseq; 10335 IS isrow, iscol; 10336 PetscBool newsubcomm = PETSC_FALSE; 10337 10338 PetscFunctionBegin; 10339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10340 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10341 PetscAssertPointer(*matredundant, 5); 10342 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10343 } 10344 10345 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10346 if (size == 1 || nsubcomm == 1) { 10347 if (reuse == MAT_INITIAL_MATRIX) { 10348 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10349 } else { 10350 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"); 10351 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10352 } 10353 PetscFunctionReturn(PETSC_SUCCESS); 10354 } 10355 10356 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10357 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10358 MatCheckPreallocated(mat, 1); 10359 10360 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10361 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10362 /* create psubcomm, then get subcomm */ 10363 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10364 PetscCallMPI(MPI_Comm_size(comm, &size)); 10365 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10366 10367 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10368 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10369 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10370 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10371 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10372 newsubcomm = PETSC_TRUE; 10373 PetscCall(PetscSubcommDestroy(&psubcomm)); 10374 } 10375 10376 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10377 if (reuse == MAT_INITIAL_MATRIX) { 10378 mloc_sub = PETSC_DECIDE; 10379 nloc_sub = PETSC_DECIDE; 10380 if (bs < 1) { 10381 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10382 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10383 } else { 10384 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10385 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10386 } 10387 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10388 rstart = rend - mloc_sub; 10389 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10390 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10391 PetscCall(ISSetIdentity(iscol)); 10392 } else { /* reuse == MAT_REUSE_MATRIX */ 10393 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"); 10394 /* retrieve subcomm */ 10395 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10396 redund = (*matredundant)->redundant; 10397 isrow = redund->isrow; 10398 iscol = redund->iscol; 10399 matseq = redund->matseq; 10400 } 10401 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10402 10403 /* get matredundant over subcomm */ 10404 if (reuse == MAT_INITIAL_MATRIX) { 10405 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10406 10407 /* create a supporting struct and attach it to C for reuse */ 10408 PetscCall(PetscNew(&redund)); 10409 (*matredundant)->redundant = redund; 10410 redund->isrow = isrow; 10411 redund->iscol = iscol; 10412 redund->matseq = matseq; 10413 if (newsubcomm) { 10414 redund->subcomm = subcomm; 10415 } else { 10416 redund->subcomm = MPI_COMM_NULL; 10417 } 10418 } else { 10419 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10420 } 10421 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10422 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10423 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10424 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10425 } 10426 #endif 10427 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10428 PetscFunctionReturn(PETSC_SUCCESS); 10429 } 10430 10431 /*@C 10432 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10433 a given `Mat`. Each submatrix can span multiple procs. 10434 10435 Collective 10436 10437 Input Parameters: 10438 + mat - the matrix 10439 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10440 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10441 10442 Output Parameter: 10443 . subMat - parallel sub-matrices each spanning a given `subcomm` 10444 10445 Level: advanced 10446 10447 Notes: 10448 The submatrix partition across processors is dictated by `subComm` a 10449 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10450 is not restricted to be grouped with consecutive original MPI processes. 10451 10452 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10453 map directly to the layout of the original matrix [wrt the local 10454 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10455 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10456 the `subMat`. However the offDiagMat looses some columns - and this is 10457 reconstructed with `MatSetValues()` 10458 10459 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10460 10461 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10462 @*/ 10463 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10464 { 10465 PetscMPIInt commsize, subCommSize; 10466 10467 PetscFunctionBegin; 10468 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10469 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10470 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10471 10472 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"); 10473 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10474 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10475 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10476 PetscFunctionReturn(PETSC_SUCCESS); 10477 } 10478 10479 /*@ 10480 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10481 10482 Not Collective 10483 10484 Input Parameters: 10485 + mat - matrix to extract local submatrix from 10486 . isrow - local row indices for submatrix 10487 - iscol - local column indices for submatrix 10488 10489 Output Parameter: 10490 . submat - the submatrix 10491 10492 Level: intermediate 10493 10494 Notes: 10495 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10496 10497 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10498 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10499 10500 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10501 `MatSetValuesBlockedLocal()` will also be implemented. 10502 10503 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10504 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10505 10506 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10507 @*/ 10508 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10509 { 10510 PetscFunctionBegin; 10511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10512 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10513 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10514 PetscCheckSameComm(isrow, 2, iscol, 3); 10515 PetscAssertPointer(submat, 4); 10516 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10517 10518 if (mat->ops->getlocalsubmatrix) { 10519 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10520 } else { 10521 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10522 } 10523 PetscFunctionReturn(PETSC_SUCCESS); 10524 } 10525 10526 /*@ 10527 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10528 10529 Not Collective 10530 10531 Input Parameters: 10532 + mat - matrix to extract local submatrix from 10533 . isrow - local row indices for submatrix 10534 . iscol - local column indices for submatrix 10535 - submat - the submatrix 10536 10537 Level: intermediate 10538 10539 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10540 @*/ 10541 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10542 { 10543 PetscFunctionBegin; 10544 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10545 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10546 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10547 PetscCheckSameComm(isrow, 2, iscol, 3); 10548 PetscAssertPointer(submat, 4); 10549 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10550 10551 if (mat->ops->restorelocalsubmatrix) { 10552 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10553 } else { 10554 PetscCall(MatDestroy(submat)); 10555 } 10556 *submat = NULL; 10557 PetscFunctionReturn(PETSC_SUCCESS); 10558 } 10559 10560 /*@ 10561 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10562 10563 Collective 10564 10565 Input Parameter: 10566 . mat - the matrix 10567 10568 Output Parameter: 10569 . is - if any rows have zero diagonals this contains the list of them 10570 10571 Level: developer 10572 10573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10574 @*/ 10575 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10576 { 10577 PetscFunctionBegin; 10578 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10579 PetscValidType(mat, 1); 10580 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10581 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10582 10583 if (!mat->ops->findzerodiagonals) { 10584 Vec diag; 10585 const PetscScalar *a; 10586 PetscInt *rows; 10587 PetscInt rStart, rEnd, r, nrow = 0; 10588 10589 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10590 PetscCall(MatGetDiagonal(mat, diag)); 10591 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10592 PetscCall(VecGetArrayRead(diag, &a)); 10593 for (r = 0; r < rEnd - rStart; ++r) 10594 if (a[r] == 0.0) ++nrow; 10595 PetscCall(PetscMalloc1(nrow, &rows)); 10596 nrow = 0; 10597 for (r = 0; r < rEnd - rStart; ++r) 10598 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10599 PetscCall(VecRestoreArrayRead(diag, &a)); 10600 PetscCall(VecDestroy(&diag)); 10601 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10602 } else { 10603 PetscUseTypeMethod(mat, findzerodiagonals, is); 10604 } 10605 PetscFunctionReturn(PETSC_SUCCESS); 10606 } 10607 10608 /*@ 10609 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10610 10611 Collective 10612 10613 Input Parameter: 10614 . mat - the matrix 10615 10616 Output Parameter: 10617 . is - contains the list of rows with off block diagonal entries 10618 10619 Level: developer 10620 10621 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10622 @*/ 10623 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10624 { 10625 PetscFunctionBegin; 10626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10627 PetscValidType(mat, 1); 10628 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10629 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10630 10631 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10632 PetscFunctionReturn(PETSC_SUCCESS); 10633 } 10634 10635 /*@C 10636 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10637 10638 Collective; No Fortran Support 10639 10640 Input Parameter: 10641 . mat - the matrix 10642 10643 Output Parameter: 10644 . values - the block inverses in column major order (FORTRAN-like) 10645 10646 Level: advanced 10647 10648 Notes: 10649 The size of the blocks is determined by the block size of the matrix. 10650 10651 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10652 10653 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10654 10655 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10656 @*/ 10657 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10658 { 10659 PetscFunctionBegin; 10660 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10661 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10662 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10663 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10664 PetscFunctionReturn(PETSC_SUCCESS); 10665 } 10666 10667 /*@ 10668 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10669 10670 Collective; No Fortran Support 10671 10672 Input Parameters: 10673 + mat - the matrix 10674 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10675 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10676 10677 Output Parameter: 10678 . values - the block inverses in column major order (FORTRAN-like) 10679 10680 Level: advanced 10681 10682 Notes: 10683 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10684 10685 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10686 10687 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10688 @*/ 10689 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10690 { 10691 PetscFunctionBegin; 10692 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10693 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10694 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10695 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10696 PetscFunctionReturn(PETSC_SUCCESS); 10697 } 10698 10699 /*@ 10700 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10701 10702 Collective 10703 10704 Input Parameters: 10705 + A - the matrix 10706 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10707 10708 Level: advanced 10709 10710 Note: 10711 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10712 10713 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10714 @*/ 10715 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10716 { 10717 const PetscScalar *vals; 10718 PetscInt *dnnz; 10719 PetscInt m, rstart, rend, bs, i, j; 10720 10721 PetscFunctionBegin; 10722 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10723 PetscCall(MatGetBlockSize(A, &bs)); 10724 PetscCall(MatGetLocalSize(A, &m, NULL)); 10725 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10726 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10727 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10728 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10729 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10730 PetscCall(PetscFree(dnnz)); 10731 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10732 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10733 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10734 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10735 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10736 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10737 PetscFunctionReturn(PETSC_SUCCESS); 10738 } 10739 10740 /*@ 10741 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10742 via `MatTransposeColoringCreate()`. 10743 10744 Collective 10745 10746 Input Parameter: 10747 . c - coloring context 10748 10749 Level: intermediate 10750 10751 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10752 @*/ 10753 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10754 { 10755 MatTransposeColoring matcolor = *c; 10756 10757 PetscFunctionBegin; 10758 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10759 if (--((PetscObject)matcolor)->refct > 0) { 10760 matcolor = NULL; 10761 PetscFunctionReturn(PETSC_SUCCESS); 10762 } 10763 10764 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10765 PetscCall(PetscFree(matcolor->rows)); 10766 PetscCall(PetscFree(matcolor->den2sp)); 10767 PetscCall(PetscFree(matcolor->colorforcol)); 10768 PetscCall(PetscFree(matcolor->columns)); 10769 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10770 PetscCall(PetscHeaderDestroy(c)); 10771 PetscFunctionReturn(PETSC_SUCCESS); 10772 } 10773 10774 /*@ 10775 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10776 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10777 `MatTransposeColoring` to sparse `B`. 10778 10779 Collective 10780 10781 Input Parameters: 10782 + coloring - coloring context created with `MatTransposeColoringCreate()` 10783 - B - sparse matrix 10784 10785 Output Parameter: 10786 . Btdense - dense matrix $B^T$ 10787 10788 Level: developer 10789 10790 Note: 10791 These are used internally for some implementations of `MatRARt()` 10792 10793 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10794 @*/ 10795 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10796 { 10797 PetscFunctionBegin; 10798 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10799 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10800 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10801 10802 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10803 PetscFunctionReturn(PETSC_SUCCESS); 10804 } 10805 10806 /*@ 10807 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10808 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10809 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10810 $C_{sp}$ from $C_{den}$. 10811 10812 Collective 10813 10814 Input Parameters: 10815 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10816 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10817 10818 Output Parameter: 10819 . Csp - sparse matrix 10820 10821 Level: developer 10822 10823 Note: 10824 These are used internally for some implementations of `MatRARt()` 10825 10826 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10827 @*/ 10828 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10829 { 10830 PetscFunctionBegin; 10831 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10832 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10833 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10834 10835 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10836 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10837 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10838 PetscFunctionReturn(PETSC_SUCCESS); 10839 } 10840 10841 /*@ 10842 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10843 10844 Collective 10845 10846 Input Parameters: 10847 + mat - the matrix product C 10848 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10849 10850 Output Parameter: 10851 . color - the new coloring context 10852 10853 Level: intermediate 10854 10855 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10856 `MatTransColoringApplyDenToSp()` 10857 @*/ 10858 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10859 { 10860 MatTransposeColoring c; 10861 MPI_Comm comm; 10862 10863 PetscFunctionBegin; 10864 PetscAssertPointer(color, 3); 10865 10866 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10867 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10868 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10869 c->ctype = iscoloring->ctype; 10870 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10871 *color = c; 10872 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10873 PetscFunctionReturn(PETSC_SUCCESS); 10874 } 10875 10876 /*@ 10877 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10878 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10879 10880 Not Collective 10881 10882 Input Parameter: 10883 . mat - the matrix 10884 10885 Output Parameter: 10886 . state - the current state 10887 10888 Level: intermediate 10889 10890 Notes: 10891 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10892 different matrices 10893 10894 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10895 10896 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10897 10898 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10899 @*/ 10900 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10901 { 10902 PetscFunctionBegin; 10903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10904 *state = mat->nonzerostate; 10905 PetscFunctionReturn(PETSC_SUCCESS); 10906 } 10907 10908 /*@ 10909 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10910 matrices from each processor 10911 10912 Collective 10913 10914 Input Parameters: 10915 + comm - the communicators the parallel matrix will live on 10916 . seqmat - the input sequential matrices 10917 . n - number of local columns (or `PETSC_DECIDE`) 10918 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10919 10920 Output Parameter: 10921 . mpimat - the parallel matrix generated 10922 10923 Level: developer 10924 10925 Note: 10926 The number of columns of the matrix in EACH processor MUST be the same. 10927 10928 .seealso: [](ch_matrices), `Mat` 10929 @*/ 10930 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10931 { 10932 PetscMPIInt size; 10933 10934 PetscFunctionBegin; 10935 PetscCallMPI(MPI_Comm_size(comm, &size)); 10936 if (size == 1) { 10937 if (reuse == MAT_INITIAL_MATRIX) { 10938 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10939 } else { 10940 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10941 } 10942 PetscFunctionReturn(PETSC_SUCCESS); 10943 } 10944 10945 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"); 10946 10947 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10948 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10949 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10950 PetscFunctionReturn(PETSC_SUCCESS); 10951 } 10952 10953 /*@ 10954 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10955 10956 Collective 10957 10958 Input Parameters: 10959 + A - the matrix to create subdomains from 10960 - N - requested number of subdomains 10961 10962 Output Parameters: 10963 + n - number of subdomains resulting on this MPI process 10964 - iss - `IS` list with indices of subdomains on this MPI process 10965 10966 Level: advanced 10967 10968 Note: 10969 The number of subdomains must be smaller than the communicator size 10970 10971 .seealso: [](ch_matrices), `Mat`, `IS` 10972 @*/ 10973 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10974 { 10975 MPI_Comm comm, subcomm; 10976 PetscMPIInt size, rank, color; 10977 PetscInt rstart, rend, k; 10978 10979 PetscFunctionBegin; 10980 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10981 PetscCallMPI(MPI_Comm_size(comm, &size)); 10982 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10983 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); 10984 *n = 1; 10985 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 10986 color = rank / k; 10987 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10988 PetscCall(PetscMalloc1(1, iss)); 10989 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10990 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10991 PetscCallMPI(MPI_Comm_free(&subcomm)); 10992 PetscFunctionReturn(PETSC_SUCCESS); 10993 } 10994 10995 /*@ 10996 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10997 10998 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10999 If they are not the same, uses `MatMatMatMult()`. 11000 11001 Once the coarse grid problem is constructed, correct for interpolation operators 11002 that are not of full rank, which can legitimately happen in the case of non-nested 11003 geometric multigrid. 11004 11005 Input Parameters: 11006 + restrct - restriction operator 11007 . dA - fine grid matrix 11008 . interpolate - interpolation operator 11009 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11010 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11011 11012 Output Parameter: 11013 . A - the Galerkin coarse matrix 11014 11015 Options Database Key: 11016 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11017 11018 Level: developer 11019 11020 Note: 11021 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11022 11023 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11024 @*/ 11025 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11026 { 11027 IS zerorows; 11028 Vec diag; 11029 11030 PetscFunctionBegin; 11031 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11032 /* Construct the coarse grid matrix */ 11033 if (interpolate == restrct) { 11034 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11035 } else { 11036 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11037 } 11038 11039 /* If the interpolation matrix is not of full rank, A will have zero rows. 11040 This can legitimately happen in the case of non-nested geometric multigrid. 11041 In that event, we set the rows of the matrix to the rows of the identity, 11042 ignoring the equations (as the RHS will also be zero). */ 11043 11044 PetscCall(MatFindZeroRows(*A, &zerorows)); 11045 11046 if (zerorows != NULL) { /* if there are any zero rows */ 11047 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11048 PetscCall(MatGetDiagonal(*A, diag)); 11049 PetscCall(VecISSet(diag, zerorows, 1.0)); 11050 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11051 PetscCall(VecDestroy(&diag)); 11052 PetscCall(ISDestroy(&zerorows)); 11053 } 11054 PetscFunctionReturn(PETSC_SUCCESS); 11055 } 11056 11057 /*@C 11058 MatSetOperation - Allows user to set a matrix operation for any matrix type 11059 11060 Logically Collective 11061 11062 Input Parameters: 11063 + mat - the matrix 11064 . op - the name of the operation 11065 - f - the function that provides the operation 11066 11067 Level: developer 11068 11069 Example Usage: 11070 .vb 11071 extern PetscErrorCode usermult(Mat, Vec, Vec); 11072 11073 PetscCall(MatCreateXXX(comm, ..., &A)); 11074 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11075 .ve 11076 11077 Notes: 11078 See the file `include/petscmat.h` for a complete list of matrix 11079 operations, which all have the form MATOP_<OPERATION>, where 11080 <OPERATION> is the name (in all capital letters) of the 11081 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11082 11083 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11084 sequence as the usual matrix interface routines, since they 11085 are intended to be accessed via the usual matrix interface 11086 routines, e.g., 11087 .vb 11088 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11089 .ve 11090 11091 In particular each function MUST return `PETSC_SUCCESS` on success and 11092 nonzero on failure. 11093 11094 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11095 11096 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11097 @*/ 11098 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11099 { 11100 PetscFunctionBegin; 11101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11102 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11103 (((void (**)(void))mat->ops)[op]) = f; 11104 PetscFunctionReturn(PETSC_SUCCESS); 11105 } 11106 11107 /*@C 11108 MatGetOperation - Gets a matrix operation for any matrix type. 11109 11110 Not Collective 11111 11112 Input Parameters: 11113 + mat - the matrix 11114 - op - the name of the operation 11115 11116 Output Parameter: 11117 . f - the function that provides the operation 11118 11119 Level: developer 11120 11121 Example Usage: 11122 .vb 11123 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11124 11125 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11126 .ve 11127 11128 Notes: 11129 See the file include/petscmat.h for a complete list of matrix 11130 operations, which all have the form MATOP_<OPERATION>, where 11131 <OPERATION> is the name (in all capital letters) of the 11132 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11133 11134 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11135 11136 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11137 @*/ 11138 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11139 { 11140 PetscFunctionBegin; 11141 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11142 *f = (((void (**)(void))mat->ops)[op]); 11143 PetscFunctionReturn(PETSC_SUCCESS); 11144 } 11145 11146 /*@ 11147 MatHasOperation - Determines whether the given matrix supports the particular operation. 11148 11149 Not Collective 11150 11151 Input Parameters: 11152 + mat - the matrix 11153 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11154 11155 Output Parameter: 11156 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11157 11158 Level: advanced 11159 11160 Note: 11161 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11162 11163 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11164 @*/ 11165 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11166 { 11167 PetscFunctionBegin; 11168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11169 PetscAssertPointer(has, 3); 11170 if (mat->ops->hasoperation) { 11171 PetscUseTypeMethod(mat, hasoperation, op, has); 11172 } else { 11173 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11174 else { 11175 *has = PETSC_FALSE; 11176 if (op == MATOP_CREATE_SUBMATRIX) { 11177 PetscMPIInt size; 11178 11179 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11180 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11181 } 11182 } 11183 } 11184 PetscFunctionReturn(PETSC_SUCCESS); 11185 } 11186 11187 /*@ 11188 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11189 11190 Collective 11191 11192 Input Parameter: 11193 . mat - the matrix 11194 11195 Output Parameter: 11196 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11197 11198 Level: beginner 11199 11200 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11201 @*/ 11202 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11203 { 11204 PetscFunctionBegin; 11205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11206 PetscValidType(mat, 1); 11207 PetscAssertPointer(cong, 2); 11208 if (!mat->rmap || !mat->cmap) { 11209 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11210 PetscFunctionReturn(PETSC_SUCCESS); 11211 } 11212 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11213 PetscCall(PetscLayoutSetUp(mat->rmap)); 11214 PetscCall(PetscLayoutSetUp(mat->cmap)); 11215 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11216 if (*cong) mat->congruentlayouts = 1; 11217 else mat->congruentlayouts = 0; 11218 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11219 PetscFunctionReturn(PETSC_SUCCESS); 11220 } 11221 11222 PetscErrorCode MatSetInf(Mat A) 11223 { 11224 PetscFunctionBegin; 11225 PetscUseTypeMethod(A, setinf); 11226 PetscFunctionReturn(PETSC_SUCCESS); 11227 } 11228 11229 /*@ 11230 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 11231 and possibly removes small values from the graph structure. 11232 11233 Collective 11234 11235 Input Parameters: 11236 + A - the matrix 11237 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11238 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11239 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11240 . num_idx - size of 'index' array 11241 - index - array of block indices to use for graph strength of connection weight 11242 11243 Output Parameter: 11244 . graph - the resulting graph 11245 11246 Level: advanced 11247 11248 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11249 @*/ 11250 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11251 { 11252 PetscFunctionBegin; 11253 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11254 PetscValidType(A, 1); 11255 PetscValidLogicalCollectiveBool(A, scale, 3); 11256 PetscAssertPointer(graph, 7); 11257 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11258 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11259 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11260 PetscFunctionReturn(PETSC_SUCCESS); 11261 } 11262 11263 /*@ 11264 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11265 meaning the same memory is used for the matrix, and no new memory is allocated. 11266 11267 Collective 11268 11269 Input Parameters: 11270 + A - the matrix 11271 - 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 11272 11273 Level: intermediate 11274 11275 Developer Note: 11276 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11277 of the arrays in the data structure are unneeded. 11278 11279 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11280 @*/ 11281 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11282 { 11283 PetscFunctionBegin; 11284 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11285 PetscUseTypeMethod(A, eliminatezeros, keep); 11286 PetscFunctionReturn(PETSC_SUCCESS); 11287 } 11288