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